为什么在哈希码中使用素数?
我只是想知道为什么在类的方法中使用素数?例如,当使用 Eclipse 生成我的方法时,总是使用质数:hashCode()
hashCode()
31
public int hashCode() {
final int prime = 31;
//...
}
引用:
这里有一个很好的哈希代码入门和关于哈希工作原理的文章,我发现(C#,但概念是可转移的):Eric Lippert的GetHashCode()的指南和规则
我只是想知道为什么在类的方法中使用素数?例如,当使用 Eclipse 生成我的方法时,总是使用质数:hashCode()
hashCode()
31
public int hashCode() {
final int prime = 31;
//...
}
引用:
这里有一个很好的哈希代码入门和关于哈希工作原理的文章,我发现(C#,但概念是可转移的):Eric Lippert的GetHashCode()的指南和规则
选择质数是为了在哈希存储桶之间最好地分配数据。如果输入的分布是随机的并且均匀分布,那么哈希代码/模数的选择无关紧要。只有当输入存在某种模式时,它才会产生影响。
在处理内存位置时,通常就是这种情况。例如,所有 32 位整数都与可被 4 整除的地址对齐。查看下表,可视化使用素模与非素模量的效果:
Input Modulo 8 Modulo 7
0 0 0
4 4 4
8 0 1
12 4 5
16 0 2
20 4 6
24 0 3
28 4 0
请注意,当使用素模量与非素模量时,几乎完美的分布。
然而,尽管上面的例子很大程度上是人为的,但一般原则是,在处理输入模式时,使用素数模量将产生最佳分布。
因为您希望要乘以的数字和要插入的存储桶数具有正交质因数分解。
假设有 8 个存储桶要插入其中。如果您用于乘以的数字是 8 的某个倍数,则插入到中的存储桶将仅由最低有效条目(根本不相乘的条目)确定。类似的条目将发生冲突。不适合哈希函数。
31 是一个足够大的素数,以至于存储桶的数量不太可能被它整除(事实上,现代 Java HashMap 实现将桶的数量保持在 2 的幂)。