HashMap
1 HashMap
1.1 JDK 1.7:数组(table)+链表(Entry)
HashMap中的核心成员:
- 初始化桶的大小:默认2^4=16;
- 桶最大值:2^30
- 负载因子:0.75
这里的负载因子指的是,当HashMap中的元素达到(160.75 = 12)时,就会自动扩容,默认扩容为原容量的两倍,这里默认扩容为162 = 32; - 存放数组的table
- 存放键值对的Entry:包含key,value,hash,next四个属性
put的流程:
get的流程:
引入问题:如果产生严重的hash冲突,链表的长度过长,严重影响查查询速度。
1.2 JDK1.8:数组(table)+链表(Node)+红黑树
解决问题:引入红黑树的数据结构,解决链表查询效率过低的问题。查询效率从O(N)改进为O(logN)。
HashMap中的核心成员与JDK1.7相比,有如下几个变化:
- 判断链表是否转为红黑树的阈值(默认为8)
- Node节点代替Entry,核心属性还是key,value,hash,next
put方法:
get方法:
引入问题:在多线程的情况下,扩容时调用resize()方法,可能出现在桶上出现循环链表。接着如果获取一个不存在的key时,计算出来的下标恰好是环形链表的话,就会出现死循环。
链接:并发场景下出现死循环详解
解决办法:将链表的头插法改为尾插法
2 ConcurrentHashMap(看完多线程后补充)
无论是JDK1.7还是JDK1.8,HashMap都没有进行同步操作的优化,所以才会出现并发问题。对于这个问题,JDK推出了ConcurrentHashMap类,专门解决并发问题。