为什么使用除法方法而不是通用哈希方法计算哈希码?

时间:2016-06-20 16:43:52

标签: c# .net algorithm

我找到了以下代码用于计算hashcode

int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int index = hashCode % buckets.Length;

为什么工程师没有选择通用的散列方法:

int index = [(ak + b) mod p)mod buckets.Length]

其中a,b0...p-1之间的随机数(p是素数)?

1 个答案:

答案 0 :(得分:2)

问题的完整答案需要咨询编写该代码的个人。所以我认为你不会得到一个完整的答案。

那说:

  1. 正如您所说的那样,“通用哈希方法”并不是唯一可能实现良好哈希码的方法。人们出于各种原因以各种方式实现哈希码计算。
  2. 更重要的是......

    1. 您引用的计算实际上并不是计算哈希码。变量名有点误导,因为虽然值是基于相关项的哈希码,但它实际上是类的内部哈希表的实现细节。通过牺牲实际哈希码中的最高位,可以使用该位将哈希表的Entry值标记为未使用。屏蔽该位,而不是例如,仅对特殊情况下的哈希码值为-1的元素进行包装,保留原始哈希码实现的分布质量(在Dictionary<TKey, TValue>之外确定)类)。
    2. 换句话说,您所询问的代码就是该代码的作者如何实现特定优化,其中通过存储其他一些所需的标志来减小Entry值的大小。目的 - 即指示是否使用特定表Entry的目的 - 在存储元素哈希码部分的相同32位值中。

      将哈希码存储在Entry值中也是一种优化。由于Entry值包含元素的TKey key值,因此实现 实际上只是总是调用key.GetHashCode()方法来获取哈希码。这是一种权衡,承认GetHashCode()方法本身并不总是优化(实际上,大多数实现,包括.NET的System.String类实现,总是从头开始重新计算哈希代码),以及因此(显然)选择将哈希码值缓存在Entry值内,而不是要求TKey值在每次需要时重新计算它。

      不要将某些其他对象的哈希代码实现的缓存和后续使用与实际的哈希代码实现混淆。后者不是你要问的代码中发生的事情,前者是。