根据Bloch对hashCode的建议:
您可以忽略任何可以从字段计算其值的字段 包含在计算中
我不明白这一点。有人能给出一个真实的例子吗?我假设任何可以从其他字段生成字段的类只会出于性能原因将其存储在另一个变量中。但这与哈希码合约有什么关系呢?
答案 0 :(得分:3)
class Example {
final int a;
final int b;
final int c;
Example(int a, int b) { this.a = a; this.b = b; this.c = a + b; }
}
此处c
计算中包含hashCode
是没有意义的:a
和b
相等的任何实例也会c
等于Objects.hash(this.a, this.b, this.c) == Objects.hash(that.a, that.b, that.c)
<=>
Objects.hash(this.a, this.b) == Objects.hash(that.a, that.b)
c
所以你所做的只是通过包含String
来“扰乱”哈希码,即使其成为不同的值,但不是以有意义的方式。
这方面的一个实际例子是String
:hash
有一个字段public int hashCode() {
int h = hash; // <-- hash is a member variable.
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
,用于存储哈希码的值,以避免重复计算(source ):
{{1}}
也许显然,这不能包含在哈希码计算中!但它可以从类中的其他字段派生。
答案 1 :(得分:1)
考虑一个有更多字段的类
class MyClass {
String name;
String surname;
String fullName;
}
在这个类中,对于几代哈希码,唯一有意义的字段是name
和surname
。其他字段fullName
由其他字段生成,可以忽略。
答案 2 :(得分:1)
但这与哈希码合约有什么关系呢?
它不会成为hashcode()
合同的一部分。您应该将其视为一种有效实施的好方法(因为它可以避免一些无助的计算)。
实际上hashCode()
的良好实现应该依赖于equals()
方法使用的相同字段。
如果您有一个包含3个字段的类,例如Addition
:
class Addition {
private float operandOne;
private float operandTwo;
private float result;
}
您不需要在result
方法中使用equals()
,因为result
在某种程度上是一种冗余信息,您不需要它以独特的方式识别Addition
个实例。
您知道,如果来自一个operandOne
实例的operandTwo
和Addition
与来自另一个operandOne
实例的operandTwo
和Addition
匹配,那么它就足够了认为他们是等于。
在hashcode()
方法中,它是一回事。