当前位置: 首页 > 后端技术 > Java

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

时间:2023-04-01 15:58:34 Java

代码中预先知道的mapmap=newHashMap(3)实例化一个map对象后,map的table实际长度是多少?答案是4。在HashMap的底层,用户设置的长度num会被修改为最近的比num大的2^n个数。如果不设置,则默认为16。索引计算源码按常识,index=hash(key)%n,那为什么hash&(n-1)和取模的效果是一样的呢?因为n的大小是2的幂,hash(key)%n==hash&(n-1)解释:n表示hash桶的长度,也就是hashmap实例的容量,为2前面说了^n^,如果不设置,默认是16,那为什么要减1呢,我们知道16的二进制值是10000,减1之后就是1111,这样我们就有了一个数在二进制中全为1,可以和哈希值&运算进行比较。&:bitwise,所有1isis1//假设我的哈希桶的长度为16//n-1是15//二进制表示为1111//假设哈希值是11110100100110101010101010101111111111111111111111011//是11110100100110011010101010101010101010101011111111111111111111111111111111111111111111111111111111111111111111111111111111成//n-1000000000000000000000000001011//结果为1011,即11,此时数据插入到第11个位置,完全取决于哈希桶的长度。即使你最后几位全为1,你插入的位置还是在n-1的范围内,这就是为什么它和取模的效果是一样的。虽然&运算后计算出的索引一定在hash桶的长度以内,但是为什么就这么肯定得到的值和%运算一样呢?而一个偶数(n)对一个数取模,结果一定是比偶数小的值,即在[0,n)范围内,这个值也是最后一个不能被n整除的数,而这个用二进制表示的时候,一定是二进制末尾的数,那么末尾有多少位呢?答案不言而喻,即表达式2^x=n中x的取值;你可能还想知道为什么&后面的数字和%后面的数字一定要相等?上面的哈希值太大了,我们取一个小一点的哈希数比如十进制的123,123%16==11123除以多少个16得到11的余数,就是701111011//十进制是123-01110000//十进制为16+16^2+64^4=00001011//十进制为11,所以余数,即计算索引的值取决于表的长度,所以将hash的二进制数x从右到左设置为0减去的数。