在JDK1.7中
//第一步,通过一系列的右移操作,让键的hash值的高16位也参与到下标计算中来。
//目的是避免高位不同、低位相同的hash值发生hash碰撞。
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
//第二步,拿到第一步计算出来的hash值和最大下标值进行&运算。
//&运算的特点是11得1,其他得0。
//最大下标值转成二进制就是00000....11111这种样子。
//这也是为什么建议数组的length最好设置为2的n次方,这样2的n次方-1的二进制末尾就为1,可以保证更多的下标被使用到
//而且与这个二进制值进行&运算不会出现数组下标越界的问题。
static int indexFor(int h, int length) {
return h & (length-1);
}
在JDK1.8中
//第一步,同样的,目的是让高位参与到下标运算中,不过1.8的算法更加的简练,效率更高。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//第二步,这个步骤同1.7中是一样的。
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
...
}