因为hashmap底层是通过数组+链表来实现的。显示通过数组然后在每个数组后面实现,可以把每个数组当作一个桶。 然后hashmap在调用put方法的时候会通过hash来计算该值在hashmap中存放的地址,在存放数据的时候需要考虑到散列度的问题, 不能把来的数据都放在痛一个桶里,所以需要一定的散列度。所以hashmap在计算数据存放的地址时通过对将自己的hash值经过无符号右移16位然后再做异或, 相当于就是自己的高16位与自己的低16位做异或,让自己的高16位低16位都参与运算使得结果更加散列(jdk 8)。 JDK7 及之前是通过hashcode与数组长度-1做 与运算,弊端在于参与运算的实际上仅仅只有hashcode的低16位甚至更低,所以相比于jdk8来说,得到的值没有jdk8散。并且在与桶长度做与运算的时候桶的 长度只能设置位2的n次方的数。在做运算的时候-1就得到了低位全是1高位全是0运算后得到的值才能小于桶长度。 h = key.hashCode(); a= h>>>16; result = h^a; 假如h = 0000 0100 1011 0011 1101 1111 1110 0001 a = 0000 0000 0000 0000 0000 0100 1011 0011 h右移16位,所以a 高16位为 0000 0000 0000 0000 低16位为h的高16位。 所以 h^a 就等于 h 0000 0100 1011 0011 | 1101 1111 1110 0001 a 0000 0000 0000 0000 | 0000 0100 1011 0011 result 0000 0100 1011 0011 | 1101 1011 0101 0010
HashMap中hash函数,以及为啥桶长度只能是2的n次方
最新推荐文章于 2024-01-06 09:46:11 发布