HashMap中HashCode的实现原理
代码
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
1. h >>> 16 是什么,有什么用?
h是hashcode。h >>> 16是用来取出h的高16,(>>>是无符号右移) 如下展示:
0000 0100 1011 0011 1101 1111 1110 0001
>>> 16
0000 0000 0000 0000 0000 0100 1011 0011
2.为什么 h = key.hashCode()) 与 (h >>> 16) 异或
在分析这个问题之前,我们需要先看看另一个事情, HashMap 如何根据 hash 值找到数组中的对象,我们看看 get 方法的代码:
if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);
看看代码中注释下方的一行代码:tab[(n - 1) & hash]
使用数组长度减一 与运算 hash 值。这行代码就是为什么要让前面的 hash 方法移位并异或。
我们分析一下:
首先,假设有一种情况,
对象 A 的 hashCode 为 1000010001110001000001111000000,
对象 B 的 hashCode 为 0111011100111000101000010100000。
如果数组长度是16,也就是 15 与运算这两个数, 你会发现结果都是0。这样的散列结果太让人失望了。很明显不是一个好的散列算法。
但是如果我们将 hashCode 值右移 16 位,也就是取 int 类型的一半,刚好将该二进制数对半切开。并且使用位异或运算(如果两个数对应的位置相反,则结果为1,反之为0),这样的话,就能避免我们上面的情况的发生。
目的是为了更加散列