前言
最近在回顾HashMap的时候,发现自己之前没有注意到的一点,是关于计算出hash值后,把这个key放在那个数组索引中。源码中是 (数组长度 - 1) & hash,这个操作等同于 hash % 数组的长度。
一、(数组长度 - 1) & hash,这个操作等同于 hash % 数组的长度?
源码位置在putVal方法的第629行:(n - 1) & hash
即为:(数组的长度 - 1) & hash(计算出的hash值)
根据传参可知道:hash为int类型的整数。
假设:数组长度:16 - 1 = 15,hash:57
二进制:1111、111001
那现在进行取余运算:57 % 16 = 9
即为 (length -1)& hash = length % hash
那么为啥呢?
二进制逢2进1,一个数右移一位 = 这个数 / 2^1。右移n位 = / 2^n。那么正好,数组的长度是2的倍数,也就是说,一个数取余 = 右移^次,移出的数字就是商。换成10进制就是:
123 % 10 = 3 相当于 123 右移一位,余3
123 % 100 = 23 相当于 123 右移两位,余23
即为:一个n进制的数字 % n进制的y倍数 = 这个数右移y位,y位即为余数。换成 8进制就是:
【10进制】156 % 8 = 4
对应
【8进制】 234 % 10 = 右移一位 = 4
【10进制】156 % 16 = 12
对应
【8进制】 234 % 20 = 右移两位 = 14 = 对应10进制 = 12
那么现在已经知道取余即为取出(2^n)n个末尾的数,咋直接拿到末尾的数呢,例如二进制的特性 ,2^n - 1 = 最大的余数,利用 & 运算,1 & 1才能 = 1,其他全都为 0,一个数 & 全是 1111…(n个1)的数字,正好拿出这个数 对 2^n的余数。
总结
以上结论全是个人已正整数猜想的,如有错误,请及时留言