【得分点】

三个条件、翻倍扩容

【参考答案】

标准回答

1.7

  1. 第一次put时,容量扩容初始化:其容量变为不小于指定容量的2的幂数(默认为16)
  2. 不是第一次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值(也有可能不计算),找到新数组中的对应位置,以头插法插入新的链表

注意:

  1. 因为是头插法,因此新旧链表的元素位置会发生转置现象。
  2. 元素迁移的过程中在多线程情境下有可能会触发死循环(无限进行链表反转),因此HashMap线程不安全。

1.8+

在扩容时,==不需要重新计算元素的hash==进行元素迁移。
而是用==原先位置key的hash值与旧数组的长度(oldCap)==进行"与"操作。

  • 如果结果是0,那么当前元素的桶位置不变。
  • 如果结果为1,那么桶的位置就是原位置+原数组 长度

值得注意的是:为了防止java1.7之前元素迁移头插法在多线程是会造成死循环,java1.8+后使用尾插法