1.HashMap、LinkedHashMap、TreeMap、Hashtable、HashSet和ConcurrentHashMap区别
Class |
初始大小 |
加载因子 |
扩容倍数 |
底层实现 |
是否允许为null |
是否允许重复 |
线程安全 |
ArrayList |
10 |
1 |
1.5 |
Object数组 |
是 |
是 |
否 |
Vector |
10 |
1 |
2 |
Object数组 |
是 |
是 |
是 |
LinkedList |
|
|
|
双向链表 |
是 |
是 |
否 |
HashMap |
16 |
0.75f |
2 |
哈希表(数组+链表+红黑树 JDK1.8) |
是 |
否 |
否 |
HashSet |
16 |
0.75f |
2 |
HashMap<E,Object>
|
否 |
否 |
否 |
Hashtable |
11 |
0.75f |
2倍+1 |
Hashtable.Entry数组 |
否 |
否 |
是 |
LinkedHashMap |
|
|
|
|
|
|
|
ConcurrentHashMap |
|
|
|
|
|
|
|
TreeMap |
|
|
|
|
|
|
|
ConcurrentHashMap性能更好。Hashtable中,synchronized是针对整张Hash表,锁住整张表让线程独占;ConcurrentHashMap允许多个修改并发进行,其关键在于使用了锁分离技术。使用多个锁来控制对hash表的不同部分进行修改。ConcurrentHashMap实现了一个名为Segment的静态内部类,使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁,只要多个修改操作发生在不同的段上,就可以实现并发进行。
针对可能跨段的方法(size()和containsValue()),按顺序锁定所有段,操作完毕后,再按顺序释放所有段的锁。注意必须“按顺序”,否则可能出现死锁,因为Segment段数组 是final修饰的,且其成员变量实际上也是final的,为了实现上保证,获取锁的顺序是固定的。
拓展:
当一个大数组需要在多个线程共享时,考虑是否把它给分层多个节点,避免大锁。并可以考虑通过hash算法进行一些模块定位。
当设计数据表的事务时(事务某种意义上也是同步机制的体现),可以把一个表看成一个需要同步的数组,如果操作的表数据太多时,
友情链接:HashMap、LinkedHashMap、TreeMap、Hashtable、HashSet和ConcurrentHashMap区别
2.ArrayList、LinkedList、Vector原理及区别
1).ArrayList和Vector都是使用数组的方式存储数据,读取效率高,插入和删除效率低
2).Vector由于使用了synchronized方法(线程安全),效率低
3).LinkedList使用双向链表实现存储,读取效率低,插入和删除效率高
友情链接:Collection、List、ArrayList、LinkList、Vector、Set
3.极高并发下HashTable和ConcurrentHashMap哪个性能更好,为什么,如何实现的
4.HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么。
5.set集合与list集合的区别
Set集合存储对象是无序,不可重复;list集合存储对象是有序的,可重复;
6.遍历map的四种方式
友情链接: Map集合的四种遍历方式
7.HashMap 的长度为什么是 2 的幂次方?
1.通过将 Key 的 hash 值与 length-1 进行 & 运算,实现了当前 Key 的定位,2 的幂次方可以减少冲突(碰撞)的次数,提高 HashMap 查询效率;
2.如果 length 为 2 的次幂 则 length-1 转化为二进制必定是 11111……的形式,在于 h 的二进制与操作效率会非常的快,而且空间不浪费;
3.如果 length 不是 2 的次幂,比如 length 为 15,则 length-1 为 14,对应的二进制为 1110,在于 h 与操作,最后一位都为 0,而 0001,0011,0101,1001,1011,0111,1101 这几个位置永远都不能存放元素了,空间浪费相当大。
更糟的是这种情况中,数组可以使用的位置比数组长度小了很多,这意味着进一步增加了碰撞的几率,减慢了查询的效率!这样就会造成空间的浪费。