详细说明一下,您会在getHashCode() 方法中的字段之间看到很多XORing,因为它是获取对象签名 的一种安全方式。签名的概念是它就像一个对象的指纹,它需要适合 32 位。许多对象使用此签名作为快速比较,(但是,如果您打算为此使用它,请查看该维基百科文章,因为您需要注意相等性和哈希码),或者一些一种寻址方式(例如 .net 的 Dictionary 和 Java 的 HashMap)。
对我来说,获取 Box 指纹的明显解决方案是简单地将这些值相加,这样如果其中任何一个发生变化,您将获得不同的指纹:
bx.Height + bx.Length + bx.Width
如果我们需要测试两个盒子的相等性,那么等号操作可能非常昂贵(即非常慢):
Box {5, 10, 15}
Box {30, 40, 50}
我们可以比较两个哈希码,看看它们不同,而不是进行完全相等比较,然后跳过完全相等比较。在字典中,这对于给我们一个快速的方法来找到一个 bin(一个元素)来放置对象是至关重要的。
但如果其中任何一个值太高,我们可能会得到整数溢出异常,因此我们不使用加法,而是使用 XOR。另一种解决方案,对于 C# 来说相当独特,是使用 unchecked{ ... } 块,但使用 XOR 被认为更优雅。
我们可以做一件更微妙的事情来提高性能,你会看到很多自动生成的哈希码方法(例如由 ReSharper 或 IntelliJ 生成的方法):
我们可以通过移动(乘)每个值来使顺序很重要。
public int hashCode() {
int result = x;
result = 31 * result ^ y;
result = 31 * result ^ z;
return result;
}
现在发生的事情是,哈希码中的每个字段实际上在生成的 32 位中都有一个位置。这意味着这两个框:
Box {1, 20, 30}
Box {1, 30, 20}
不会有相同的哈希码(它们与您当前的系统会有相同的哈希码,但它们是不同的!)
关于哈希码,你想知道的比你想知道的还要多,但我还要说一件事。
在 Java/Scala 和 .net 框架中,如果您重载 equals 或 hash-code,您必须也重载另一个。您必须还确保如果两个对象 A 和 B 具有不同的哈希码,则对 A.Equals(B) 的调用必须为假。