是
public override int GetHashCode()
{
return Word.GetHashCode();
}
真的一样
public override int GetHashCode()
{
return (int) Word.GetHashCode() * 7;
}
关于唯一性?
Word
是类型String
编辑:我忘了说,在程序中哪个更好,选项 1 或 2?
是
public override int GetHashCode()
{
return Word.GetHashCode();
}
真的一样
public override int GetHashCode()
{
return (int) Word.GetHashCode() * 7;
}
关于唯一性?
Word
是类型String
编辑:我忘了说,在程序中哪个更好,选项 1 或 2?
很明显,实现中的任何冲突Word.GetHashCode()
都会导致实现中的冲突(int) Word.GetHashCode() * 7
,因为相同的数字相乘会产生相同的结果。
一个更有趣的问题是,第一个实现中的非冲突哈希码是否会导致第二个实现中的冲突。事实证明,答案是否定的,因为 和 的范围int
是7
互素数。因此,乘法在丢弃溢出后会产生唯一的映射。
您可以使用两字节哈希码运行一个小测试,看看会发生什么:
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
模 2 16,并验证该范围内的每个数字是否只生成一次。
Count of duplicate mappings found: 0
如果你7
用偶数替换,结果会很不一样。现在,来自原始集合的多个哈希码将映射到目标集合中的单个哈希码。如果您记得乘以偶数总是使最低有效位为零,您可以直观地理解这一点。因此,一些信息会丢失,这取决于偶数可以被二除多少次。
哪一个更好?
没有区别。
注意:以上假设您忽略整数溢出。
由于您没有在unchecked
上下文中运行代码,因此后者会在任何溢出时抛出异常,这很有可能(6/7 的哈希范围会抛出,因此通常均匀分布的哈希代码具有 ~ 6/7 的机会抛出异常)。