HashMap的扩容机制
【得分点】
三个条件、翻倍扩容
【参考答案】
标准回答
1.7
- 第一次put时,容量扩容初始化:其容量变为不小于指定容量的2的幂数(默认为16)
- 不是第一次put时,扩容:新容量 = 旧容量 * 2 ,新阈值 = 新容量 * 加载因子
1.8
向HashMap中添加数据时,有三个条件会触发它的扩容行为:
1、HasMap初始化的时候,会指定初始化大小,以及扩展阀值,如果不指定,就使用默认值,此时数组为null;
2、向HashMap中存值的时候,如果数组为null或者为空,开始第一次扩容,创建初始化大小的数组,默认为16
3、如果当链表的长度达到8,同时数组的长度小于64,进行扩容
4、如果当hashMap的元素总量达到了阀值【正常为数组长度*0.75,如果数组长度和阈值计算的结果大于等于2^30则阈值为 2^31-1】,进行扩容;
5、扩容每次将容量翻一番;
加分回答
1.7:
在准备好新的数组后,map会遍历数组的每个“桶”,然后遍历桶中的每个Entity,重新计算其hash值(也有可能不计算),找到新数组中的对应位置,以头插法插入新的链表。
注意:
- 因为是头插法,因此新旧链表的元素位置会发生转置现象。
- 元素迁移的过程中在多线程情境下有可能会触发死循环(无限进行链表反转),因此HashMap线程不安全。
1.8+
在扩容时,==不需要重新计算元素的hash==进行元素迁移。
而是用==原先位置key的hash值与旧数组的长度(oldCap)==进行"与"操作。
- 如果结果是0,那么当前元素的桶位置不变。
- 如果结果为1,那么桶的位置就是原位置+原数组 长度
值得注意的是:为了防止java1.7之前元素迁移头插法在多线程是会造成死循环,java1.8+后使用尾插法
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果