调用HashMap的put方法将一个键值对存到map中,会先计算key的散列值。该散列值是int基本类型,int的范围为~
,用这个散列值来确定map的数组下标(jdk8之前HashMap的数据结构是数组+链表,jdk8之后又加上了红黑树)。但这散列值太大,map的容量不可能这么大,会内存溢出。所以需要通过一种方式将这个key的散列值与map的容量对应起来。比如说将散列值与map容量取模,这样得到的结果一定小于容量了,就可以拿来做数组下标了,但取模计算的速度较慢。分析一下HashMap的源码,
jdk采用了这种方式计算下标:
(n - 1) & hash,想象一下底层的二进制计算,这是一个按位与计算,所以n - 1的二进制数只要有一位为0,这一位按位与后还是0,这会造成map中有的桶永远是空的。故而n - 1要是都是由1组成的二进制数的话,算出的下标就会分布得均匀,put时就减少了哈希碰撞,提高了程序性能。2的一次方的二进制数是10,二次方的二进制数是100,依次下去是1000、10000、100000,这些二进制数减一得到的二进制数就都是1组成的二进制数了。这样的二进制数和hash做按位与计算得到的数组下标才会分布得均匀。