我在我正在研究的代码库中发现了两种带有哈希码方法的数据类型,我不完全理解它们被选中的原因:
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() << 2;
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
}
比特移位操作如何使这些哈希值更好?
答案 0 :(得分:2)
假设您有一个由Point
和x
变量代表的y
数据结构。如果没有位移,(1,0)
的哈希码值将为1
,(0,1)
的哈希码也将为1
。现在对位移做同样的事情,对于(1,0)
,我们得到的散列码为1
,但对于(0,1)
,我们现在得到的散列码为4
比特移位提供的是,如果您有相同的输入但是以不同的顺序想要获得不同的哈希码,那么(1,0)
和(0,1)
最终不会落入相同的哈希桶并降低您的哈希集/字典性能。
通常情况下,你会做的偏差大于左移两次。如果处理Int32.MaxValue
附近的哈希码,则Bitshifting还会导致数据被截断。这是我通常使用的模式
public override int GetHashCode()
{
unchecked
{
var hashCode = X;
hashCode = (hashCode*397) ^ Y;
hashCode = (hashCode*397) ^ Z;
return hashCode;
}
}
(这是Resharper的“插入比较方法”功能附带的默认实现。要添加更多字段,您只需继续hashCode = (hashCode*397) ^ XXXXXXX
)
将*
与unchecked
而不是<<
一起使用任何大于Int32.MaxValue
的值只会溢出而不会出错。