阿里P5-集合相关

阿里P5-集合相关

1.描述下Java常用集合类的继承关系?
Java是一门面向对象的语言,在实际的编程中也常常会对多个对象进行操作,此时常常就需要用到集合来存储多个对象。数组虽然也可以存储对象,但长度是固定的;集合长度是可变的,数组中可以存储基本数据类型,集合只能存储不同类型的对象。
在这里插入图片描述
Collection (集合的最大接口)继承它的常用子类有:
——List 可以存放重复的内容
——Set 不能存放重复的内容,重复内容靠hashCode()和equals()两个方法区分
——Queue 队列接口(图中未画出,更详细的图可以参见:https://img-blog.csdn.net/20160124221843905
a.List的常用子类
List中元素可以重复,并且是有序的(这里的有序指的是按照放入的顺序进行存储。如按照顺序把1,2,3存入List,那么,从List中遍历出来的顺序也是1,2,3)。
——ArrayList   线程不安全,查询速度快

——Vector   线程安全,但速度慢,已被ArrayList替代

——LinkedList  基于双向链表实现,增删速度快
b.Set
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
——HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。
——TreeSet:有序的存放:TreeSet线程不安全,可以对Set集合中的元素进行排序通过compareTo或者compare方法来保证元素的唯一性,元素以二叉树的形式存放。
2.ArrayList、LinkedList、Vector的区别。
ArrayList和Vector是按照顺序将元素存储(从下表为0开始),删除元素时,删除操作完成后,需要使部分元素移位,默认的初始容量都是10.ArrayList和Vector是基于数组实现的,LinkedList是基于双向链表实现的(含有头结点)。所以ArrayList与LinkedList相比,ArrayList查找和访问元素的速度较快,但新增,删除的速度较慢。
对于ArrayList,它在集合的末尾删除或添加元素所用的时间是一致的,但是在列表中间的部分添加或删除时所用时间就会大大增加。但是它在根据索引查找元素的时候速度很快。
对于LinkedList则相反,它在插入、删除集合中任何位置的元素所花费的时间都是一样的,但是它根据索引查询一个元素的时候却比较慢。
3.HashMap、HashTable以及ConCurrentHashMap的区别?
首先我们来看一下Map这个数据结构,Map用于存储“key-value”元素对,它将一个key映射到一个而且只能是唯一的一个value。Map可以使用多种实现方式,HashMap的实现采用的是hash表;而TreeMap采用的是红黑树。

A.HashMap
实现了Map接口,实现了将唯一键隐射到特定值上。允许一个NULL键和多个NULL值。非线程安全。有两种方法可以解决HashMap的线程安全问题:
a.Java的Collections库中的synchronizedMap()方法
b.使用ConcurrentHashMap
SynchronizedHashMap
会同步整个对象
每一次的读写操作都需要加锁
对整个对象加锁会极大降低性能
这相当于只允许同一时间内至多一个线程操作整个Map,而其他线程必须等待
它有可能造成资源冲突(某些线程等待较长时间)
SynchronizedHashMap会返回Iterator,当遍历时进行修改会抛出异常

B.HashTable
类似于HashMap,但是不允许NULL键和NULL值,比HashMap慢,因为它是同步的。HashTable是一个线程安全的类,它使用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占。

C.ConcurrentHashMap
ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的Hashtable,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。但是JDK1.8的实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,Node是ConcurrentHashMap存储结构的基本单元,继承于HashMap中的Entry,用于存储数据,并发控制使用Synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap。

当你程序需要高度的并行化的时候,你应该使用ConcurrentHashMap
尽管没有同步整个Map,但是它仍然是线程安全的
读操作非常快,而写操作则是通过加锁完成的
在对象层次上不存在锁(即不会阻塞线程)
锁的粒度设置的非常好,只对哈希表的某一个key加锁
ConcurrentHashMap不会抛出ConcurrentModificationException,即使一个线程在遍历的同时,另一个线程尝试进行修改。
ConcurrentHashMap会使用多个锁

Hashtable 和 HashMap的不同点:
这两个类主要有以下几方面的不同:
Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。而在Hashtable中,无论是key还是value都不能为null。
这两个类最大的不同在于Hashtable是线程安全的,它的方法是同步了的,可以直接用 在多线程环境中。而HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。因此,在Collections类中提供了一个方法返回一个 同步版本的HashMap用于多线程的环境:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
2         return new SynchronizedMap<K,V>(m);
3  }

该方法返回的是一个SynchronizedMap的实例。SynchronizedMap类是定义在Collections中的一个静态内部类。它实现了Map接口,并对其中的每一个方法实现,通过synchronized关键字进行了同步控制。(但是这个方法依旧线程不安全)。

Hashtable 和ConcurrentHashMap
效率低下的HashTable容器
HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况 下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞 或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。
锁分段技术
HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把 锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是 ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据 的时候,其他段的数据也能被其他线程访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值