hashmap 的内存结构是数组加链表
为了使值均匀的分布在数组里,尽可能减少碰撞,增加查询的效率,减少空间的浪费。
可以使用key的hashcode去查找,因为hash的时间复杂度是1,速度比较快。
然后hash值取模 % 数组的长度 -1。
但是与运算& 比取模%速率要快些。
所以Java官方使用了与运算&。
运算&的特点是11为1,10 或者00为0。
这里有个比较巧妙的地方就是:
2的n次幂转换为2进制最后一位都是0
8 1000 16 10000
因为key的hash值是跟数组的长度减一与运算&
所以数组从长度减一以后,后几位就变成了1111,全都是1
不同的key算得得index相同的几率较小
举个例子
两组的hashcode均为8 1000 和9 1001
分别与数组长度-1 15(1111)和14(1110)取与运算
对15运算分别是 1001 1000,14运算都是1000
发生碰撞的几率大了很多
因为14二进制的最后一位是0
所以不管什么hash只跟14取与运算最后一位肯定也是0
所以数组下标最后一位是1的肯定不会存放数据
比如0001,0011,0101,1001,1011,0111,1101
空间浪费相当大,发生碰撞的几率会更高
所以hashMap的容量扩容时一定是2的n次幂