C# GetHashCode Implementation

本文关键字:Implementation GetHashCode | 更新日期: 2023-09-27 18:09:27

public override int GetHashCode()
{
    return Word.GetHashCode();
}

一样
public override int GetHashCode()
{
    return (int) Word.GetHashCode() * 7;
}

关于唯一性?

WordString

EDIT:我忘了说,在程序中实现哪个更好,选项1还是选项2?

C# GetHashCode Implementation

很明显,Word.GetHashCode()实现中的任何冲突都会导致(int) Word.GetHashCode() * 7实现中的冲突,因为相同的数字相乘会产生相同的结果。

一个更有趣的问题是,第一个实现中的非冲突哈希码是否会导致第二个实现中的冲突。结果证明答案是"否",因为int7的范围互为素数。因此,删除溢出后,乘法产生唯一映射。

您可以用两个字节的哈希码运行一个小测试,看看会发生什么:

const int Max = 1<<16;
var count = new int[Max];
for (int i = 0 ; i != Max ; i++) {
    count[(i * 7) & (Max-1)]++;
}
var notOne = 0;
for (int i = 0 ; i != Max ; i++) {
    if (count[i] != 1) {
        notOne++;
    }
}
Console.WriteLine("Count of duplicate mappings found: {0}", notOne);

该程序将哈希码值i映射到7 * i模216,并验证范围内的每个数字恰好产生一次。

Count of duplicate mappings found: 0

演示。

如果你用一个偶数替换7,结果将会非常不同。现在,原始集中的多个哈希码将被映射到目标集中的单个哈希码。如果你回想一下,乘以一个偶数总是使最低有效位为零,你就能直观地理解这一点。因此,一些信息会丢失,这取决于偶数能被2除以多少次。

哪个更好?

没有差别。

注意:以上假设您忽略了整数溢出

由于您没有在unchecked上下文中运行代码,因此后者将在任何时候出现溢出时抛出异常,这是合理的(哈希范围的6/7会抛出,因此通常均匀分布的哈希代码有~6/7的机会抛出异常)。