HashMap计算key索引算法为什么是hash(key)&(n = table.length - 1)

HashMap计算key索引算法为什么是hash(key)&(n = table.length - 1)

前置知识

在代码中 Map map = new HashMap(3) 这样实例化一个map对象后,map的table长度实际是多少?

答案是4,在HashMap底层,会根据用户设置的长度num变更为比num大的最近的一个$2^n$数,如果未设置则是默认16

HashMap actual table length

index计算源代码

key_index

按常理来说 index = hash(key) % n,那为什么 hash & (n-1) 和 取模效果一样呢? 因为n的大小是2的幂次方,所以hash(key) % n == hash & (n-1)
解释:
n表示哈希桶的长度,就是hashmap这个实例的容量,刚才说了会是2^n^,不设置默认是16,那为什么要减1,我们知道16的二进制是10000,减1后就变成1111,这样我们有了一个二进制全部为1的数后就可以和hash值进行&运算。
**&:按位与,都为1才是1**

// 假设我的哈希桶的长度是16
// n - 1 即为 15
// 二进制表示为 1111
// 假设 hash值 是 111101001001101010101010111011
// 即
111101001001101010101010111011 // hash
000000000000000000000000001111 // n-1
000000000000000000000000001011 // 结果为 1011 即 11

此时数据插入到第11的位置,这个完全取决于哈希桶的长度。就算你最后几位都是1,你插的位置还是在n-1的范围内,这就是为什么和取模的效果一样。
虽然通过&运算之后算出来的index肯定在哈希桶的长度之内,但是为什么就那么确定得到的值是和%运算是一样的呢?
而一个数模上一个偶数(n),结果肯定是小于这个偶数的值,即在[0, n)范围内,这个值也是这个数除n除不尽的最后的数,而用二进制表示这个数的时候肯定也就是这个二进制末尾的数,那么是末尾几位的数呢? 答案不言而明,也就是 $2^x$=n 这个表达式的x的值;
可能还会疑惑,为什么 &后面的数和% 后之后剩下的数一定是相等的呢?
上面hash值太大,举一个hash小一点的数比如十进制的123,123%16==11 123除多少个16得到余数是11呢,是7个

  0111 1011 // 十进制为 123
- 0111 0000 // 十进制为 16 + 16^2 + 64^4
= 0000 1011 // 十进制为 11

所以余数即计算后的index的值取决于table的length,就把该hash的二进制从右到左x位数置为0的数减掉。  

喜欢的话,关注下我的公众号 JavaQuest

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值