e.hash & oldCap == 0 详细解读

e.hash & oldCap == 0 详细解读

按(e.hash & oldCap) 是否等于0分两种情况(推导过程中要时刻留意:扩容前后的数组长度都为2的n次幂,这个是HashMap底层源码规定的):

情况1:【推导过程1】当e.hash&oldCap等于0时,e在新旧数组中的索引位置不变:(2oldCap-1)& e.hash = (oldCap -1) & e.hash

情况2:【推导过程2】当e.hash&oldCap不等于0的元素,e在新数组中的索引位置是其在旧数组中索引位置的基础上再加上旧数组长度个偏移量: (2oldCap-1)& e.hash = (oldCap -1) &e.hash+oldCap

oldCap 是table的容量,按照源码的策略,一定是2^n次方,也就代表着该2进制一定只有一个1,剩余的都是0;如果想要保证e.hash&oldCap ==0,则只需要e.hash在对应oldCap二进制位在1的那位为0,就可以保证最后的按位与操作(&)结果为0;如果e.hash&oldCap !=0 ,则只需要e.hash在对应oldCap二进制位在1的那位为1,就可以保证最后的按位与 操作(&)不等于0

假设 oldCap = 16 = 2^4 = 10000(二进制)

推导过程1:

想要满足e.hash&oldCap ==0,假设 e.hash = 01111 (注意,这里的e.hash经过最初的hash(key)计算的),注意这个01111中0的位置是对应着oldCap 二进制中唯一的那位1的位置)

10000 & 01111

则oldCap & e.hash = 10000 & 01111 = 00000(二进制) = 0(十进制)

在添加元素的时候,是通过这种计算方式来为即将添加的元素在数组中找到对应的下标

在这里插入图片描述

而现在我们是将数组容量扩容到了两倍,公式肯定要有所修改

(2oldCap-1)& e.hash = (2^5 - 1)& 0 1111 = 01 1111 & 0 1111 = 00 1111(二进制)= 15(十进制)

(oldCap -1)& e.hash = (2^4 - 1)& 0 1111 = 0 1111 & 0 1111 = 0 1111(二进制) = 15 (十进制)

由此可见,如果满足 e.hash&oldCap ==0 ,旧数组中元素的下标位置在新数组的元素下标的位置是一样的

(e.hash & oldCap) == 0
if (loTail != null) {
    loTail.next = null;
    // 旧数组中元素的下标位置在新数组的元素下标的位置是一样的
    newTab[j] = loHead;
}
推导过程2:

想要满足e.hash&oldCap !=0,假设e.hash = 11111(注意,这里的e.hash经过最初的hash(key)计算的),注意这个11111中第一个1的位置是对应着oldCap 二进制中唯一的那位1的位置)

10000 & 11111

则oldCap & e.hash = 1 0000 & 1 1111 = 1 0000 (二进制) = 16(十进制)

在添加元素的时候,是通过这种i = (n - 1) & hash计算方式来为即将添加的元素在数组中找到对应的下标

(2oldCap-1)& e.hash = (2^5 - 1)& 1 1111 = 01 1111 & 1 1111 = 0001 1111(二进制)= 31(十进制)

(oldCap -1)& e.hash = (2^4 - 1)& 1 1111 = 0 1111 & 1 1111 = 0000 1111(二进制) = 15 (十进制)

可以发现 (oldCap -1)& e.hash + oldCap = 15 + 16 = 31 = (2oldCap-1)& e.hash

由此可见,如果满足e.hash&oldCap != 0 ,旧数组中元素的下标位置 + 旧数组容量 = 元素在新数组中下标的位置

e.hash & oldCap) == 0
if (hiTail != null) {
    hiTail.next = null;
    newTab[j + oldCap] = hiHead;
}

以上仅为个人解读,如有误解,请在评论区指教,谢谢

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值