Java 为什么HashMap(JDK1.8)中的hash计算不';T需要考虑负面哈希码作为CONCURNESASMAP吗?
在Java 为什么HashMap(JDK1.8)中的hash计算不';T需要考虑负面哈希码作为CONCURNESASMAP吗?,java,hashmap,concurrenthashmap,Java,Hashmap,Concurrenthashmap,在HashMap:(h=key.hashCode())^(h>>16) 在ConcurrentHashMap:(h^(h>>16))&HASH_位 当散列位是0x7fffffff时,通过散列位它可以始终是正数。实际上它处理负索引计算。乍一看并不明显,但在访问元素(键或值)时,某些地方会进行计算 int index=(n-1)&hash,其中n是表的长度 它只处理负索引 好的,HashMap总是使用大小为2次方的数组(例如16、32、64,等等) 假设我们的容量为256(0x100),即2^8。
HashMap
:(h=key.hashCode())^(h>>16)代码>
在ConcurrentHashMap
:(h^(h>>16))&HASH_位代码>
当散列位
是0x7fffffff
时,通过散列位
它可以始终是正数。实际上它处理负索引计算。乍一看并不明显,但在访问元素(键或值)时,某些地方会进行计算
int index=
(n-1)&hash
,其中n
是表的长度
它只处理负索引
好的,HashMap
总是使用大小为2次方的数组(例如16
、32
、64
,等等)
假设我们的容量为256
(0x100
),即2^8
。
减法1之后,我们得到256-1=255
,即0x100-0x1=0xFF
减法产生了在0
到length-1
之间获得适当的bucket索引,按位和散列需要精确的位掩码
256 - 1 = 255
0x100 - 0x1 = 0xFF
260
(0x104
)的散列将按位与0xFF
进行AND运算,以生成4
的桶编号
257
(0x101
)的散列将按位与0xFF
进行AND运算,以生成1
的桶编号
为什么在HashMap(JDK1.8)中散列的计算不需要考虑CONShuthShash映射的负哈希码?
最终,散列为负数的情况(扩散后)也需要在HashMap
情况中考虑。只是在代码的后面会发生这种情况
例如,在getNode
(Java 8)中,您会发现:
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
节点[]选项卡;节点第一,e;int n;K;
如果((tab=table)!=null&(n=tab.length)>0&&
(first=tab[(n-1)&散列]!=null){
由于tab.length
是2的幂,因此tab.length-1
是将hash
减少为数组下标的合适位掩码
您可以放心,在HashMap
或ConcurrentHashMap
的每个实现中,都有一些代码将哈希代码减少到适合用作下标的数字。它将出现在……某个地方
但同时…不要期望这些类的代码易于阅读。所有集合类都经过多次修改/调优,在各种测试用例中获得尽可能好的(平均)性能。对不起,我错了。似乎(n-1)&hash可以将其保持为正数。那么为什么ConcurrentHashMap要做额外的事情呢?可能是因为它需要做。可能这只是作者的疏忽。您需要对代码进行取证分析,以确定哪些…我认为我自己做不到。(提示!)