HashMap元素的插入流程以及扩容操作

您所在的位置:网站首页 hashmap是如何解决hash碰撞的 HashMap元素的插入流程以及扩容操作

HashMap元素的插入流程以及扩容操作

2023-09-05 14:44| 来源: 网络整理| 查看: 265

为什么java8不需要调用hash函数重新计算下标 下标计算公式为 index = (n - 1) & hash; 假设扩容前的长度为16,key的hash值为xxxx 1011,则扩容前元素的下标计算过程为:

int index =(n - 1) & hash; = (16 - 1) & xxxx 1011 = 15 & xxxx 1011 = 1111 & xxxx 1011 = 1011 = 11

因为与(&)计算原理为必须对位的两个值都是1才为1,所以这里实际参与计算的只有hash值的低4位; 由于HashMap的容量位2的次方,所以容量-1可以转化为N个相连的数位1; 在发生扩容后,容量增长为原来的两倍 - 32,此时参与重新计算下标的值为(n-1)31,转化为二进制为 1 1111;

int index =(n - 1) & hash; = (32 - 1) & xxxx 1011 = 31 & xxxx 1011 = 1 1111 & xxxx 1011

我们暂停在这一步,画图看一下两次运算结构的差别

在这里插入图片描述 可以看到扩容前hash值实际参与运算的数位为4,扩容后实际参与运算的数位为5;由于扩容前后hash值是不变的,所以运算结果的后4位也不会发生改变; 在这里插入图片描述 当扩容后的最高位,也就是第5位对应的x值为0时,最后的运算结果和原来一样,即此节点在新表中的下标和原来一样,归入不需要迁移的链表中; 当第5位对应的x值为1时,最后运算结果的后4为和原来一样,只是第五位变成了1,下标值发生了改变,归入需要迁移的链表中; 可以理解为:

11011 = 1011 + 1 0000 ; 新下标 = 旧下标 + 旧容量;

总结:

当x=0时(也就是源码中 (e.hash & oldCap) == 0),此节点在新表中的位置不需要移动。当x=1时(也就是源码中 (e.hash & oldCap) == 1),此节点在新表中的位置发生了移动,移动的方式为:新下标 = 旧下标 + 旧容量。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3