概述
我们知道hsahmap的底层是由链表和数组构成的,为了最有效的提高数据的存取效率,hashMap每次保存数据都是分散保存在不同的index位置上。
如何实现数组的散列性呢?一般的想法可以是利用key值的哈希值(hash)对数组的长度(length)取余,即hash%length。但是hashMap的源码作者是利用一种更高效的计算手段,也就是利用哈希值和数组长度的二进制表示进行位运算,具体来说就是hash&(length-1),但是必须保证length等于2的n次幂。
原理
因为我们知道length(2^n)转为二进制位是1+n个0,length-1转为二进制位是0+n个1。length-1与hash值进行位运算后,hash值的低n位都被保存下来,而其它高位则被舍弃掉了。后面的n位的10进制值刚好在0-length之间,也就是等于hash%length取余。
问什么length不能是奇数或其它类型的偶数呢
问什么不能是奇数
length = 2^n-1,那么length-1的二进制表示的最后一位必定为0,那么与哈希值进行位运算的结果的最后一位一定也是0,即运算结果一定是偶数,那么保存数据时,都会保存在数组的偶数index,奇数index没有数据保存,这样不仅增大了哈希碰撞的概率,并且一半的数组空间都会浪费掉。
问什么不能是非2^n的偶数
length若为非2^n的偶数,那么length-1的二进制表示的后n位中,必然存在若干个二进制位的值为0。那么位运算后的结果上述的二进制位也为0,结果就是数组对应下标(index)的位置永远不会被保存数据。
综上,无论length是奇数,还是其它类型的偶数,注定数组某些下表的位置永远不会被用到保存数据。导致空间浪费,哈希碰撞的概率上升。