Zie*_*emo 9 java collections hash hashmap hashcode
为什么HashMap在索引上插入新的Node:
tab[(n - 1) & hash]
哪里hash = key.hashCode() ^ key.hashCode() >>> 16
和哪个n = tab.length
阵列Node<K,V>
.
为什么HashMap的不把节点就是这样:tab[hash]
?它只是另一个散列函数,比如在大多数hashCode()
方法中乘以31 吗?在此先感谢您的解释!
har*_*old 10
因为hash
可能超出范围.
"规范解决方案"是使用数组长度获取散列的(正)模数,此代码使用数组具有2的幂长度来替换昂贵的模数的事实(模数为a使用廉价的按位AND,可以很好地优化常量.
Ani*_*kur 10
哈罗德的一个很好的描述,但我觉得没有一个例子是不够的.所以继承人 -
每当创建一个新的Hasmap时,内部Node []表的数组大小总是2的幂,并且以下方法保证 -
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
Run Code Online (Sandbox Code Playgroud)
所以假设您提供的初始容量为5
cap = 5
n = cap - 1 = 4 = 0 1 0 0
n |= n >>> 1; 0 1 0 0 | 0 0 1 0 = 0 1 1 0 = 6
n |= n >>> 2; 0 0 1 1 | 0 1 1 0 = 0 1 1 1 = 7
n |= n >>> 4; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 8; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 16; 0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
return n + 1 7 + 1 = 8
Run Code Online (Sandbox Code Playgroud)
所以表大小是8 = 2 ^ 3
现在可以将元素放在map中的索引值为0-7,因为表大小为8.现在让我们看一下put方法.它查找桶索引如下 -
Node<K,V> p = tab[i = (n - 1) & hash];
Run Code Online (Sandbox Code Playgroud)
其中n是数组大小.所以n = 8.就像说的一样
Node<K,V> p = tab[i = hash % n];
Run Code Online (Sandbox Code Playgroud)
所以我们现在需要看到的是如何
hash % n == (n - 1) & hash
Run Code Online (Sandbox Code Playgroud)
让我们再举一个例子.让我们说一个值的哈希是10.
hash = 10
hash % n = 10 % 8 = 2
(n - 1) & hash = 7 & 10 = 0 1 1 1 & 1 0 1 0 = 0 0 1 0 = 2
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.更多细节
PS:以上链接转到我的博客,其中有更详细的示例解释.