在许多GetHashCode实现中,为什么在xoring之前乘以素数?

我知道在xoring之前乘以大量的数字应该有助于分配错误的操作数,但为什么乘数应该是素数呢?

有关:
散列函数为什么要使用素数模数?

关闭,但不是很重复:
为什么String中的Java hashCode()使用31作为乘数?

计算生活博客上有一篇很好的文章 ,详细讨论了这个主题。 它最初是作为对我在问题中链接的Java hashCode()问题的响应而发布的。 根据这篇文章:

Primes是唯一的数字。 它们的独特之处在于,素数与任何其他数字的乘积最有可能是唯一的(不像当然的素数本身那样独特),因为使用素数来构成它。 此属性用于散列函数。

给定一个字符串“Samuel”,您可以通过将每个组成数字或字母与素数相乘并将它们相加来生成唯一的哈希值。 这就是使用素数的原因。

然而,使用素数是一种古老的技术。 关键在于理解,只要您可以生成足够独特的密钥,您也可以转移到其他散列技术。 到这里了解更多有关没有素数的哈希的主题。

乘以非素数具有比数量小得多的循环重复模式。 如果使用素数,则保证循环重复模式至少与素数一样大。

考虑最简单的乘法:x2。

它等同于左位移。 换句话说,它确实没有“随机化”数据,它只是将其移位。

与x4相同,或任何两个幂。 原始数据完好无损,只是移位了。

现在,乘以其他数字(两个非幂)并不是那么明显,但仍然有相同的问题,或多或少。 原始数据完整无缺或简单转换。 (例如,x5与left-bitshift两个位置相同,然后添加原始数据)。

GetHashCode的要点是尽可能随机地分配数据。 乘以素数可以保证答案不会像比特移位或向自身添加数字那样更简单。