我没有看到这种方法可以避免碰撞。我认为如果key.hashcode大于table.length,则会发生碰撞。
更新:
实际上我指的是JDK 1.8中的HashMap#hash
,并且对于向下传播较高位的好处有点困惑。
现在,我想在link的帮助下我很清楚,好处是:
对于碰撞,如果密钥的数量大于表的长度,则无论使用何种哈希方法都会发生冲突。
答案 0 :(得分:2)
让我们说你天真地使用
索引到一个哈希表int index = hashcode % table.length;
在某些常见用例中,这可能会导致许多冲突。例如,假设table.length是2的小幂(如32或64)。在这种情况下,只有哈希码的低阶位确定索引。如果您的对象的哈希码仅在高位中有所不同,则会导致大量冲突。位移允许哈希码的高位也影响计算的索引。
答案 1 :(得分:2)
原因在于评论:
计算key.hashCode()并将散列(XOR)更高的散列位降低。因为该表使用2次幂掩蔽,所以仅在当前掩码之上的位中变化的散列组将始终发生冲突。 (在已知的例子中有一组Float键,在小表中保存连续的整数。)
用简单的话来说,Key#hashcode
(我们关心的最后一位)对于实际上不同的密钥是相同的。这会产生冲突,因为这些条目最终将在同一个桶中。
条目的位置取决于现有存储桶的数量或最后的n位,如您所见:
int index = (n - 1) & hash
如果hashmap不会再次重新哈希 - 这意味着那些最后一位不同的条目最终将在同一个桶中,搜索时间= =更慢。
使用XOR
的原因 - 因为它具有{/ 1}}和1
的50/50%分布(而不是0
或|
有75/25或25/75)。
使用&
操作代替&
,不仅仅用于速度,而是因为哈希码是%
并且可以是负数。负数上的模数将为负数 - 意味着负数桶...因此使用int
将生成正指数。