Hashcode和排除字段

时间:2017-04-28 10:44:20

标签: java hash hashcode

根据Bloch对hashCode的建议:

  

您可以忽略任何可以从字段计算其值的字段   包含在计算中

我不明白这一点。有人能给出一个真实的例子吗?我假设任何可以从其他字段生成字段的类只会出于性能原因将其存储在另一个变量中。但这与哈希码合约有什么关系呢?

3 个答案:

答案 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是没有意义的:ab相等的任何实例也会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来“扰乱”哈希码,即使其成为不同的值,但不是以有意义的方式。

这方面的一个实际例子是Stringhash有一个字段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;
}

在这个类中,对于几代哈希码,唯一有意义的字段是namesurname。其他字段fullName由其他字段生成,可以忽略。

答案 2 :(得分:1)

  

但这与哈希码合约有什么关系呢?

它不会成为hashcode()合同的一部分。您应该将其视为一种有效实施的好方法(因为它可以避免一些无助的计算)。

实际上hashCode()的良好实现应该依赖于equals()方法使用的相同字段。
如果您有一个包含3个字段的类,例如Addition

class Addition {
  private float operandOne;
  private float operandTwo;
  private float result;
}

您不需要在result方法中使用equals(),因为result在某种程度上是一种冗余信息,您不需要它以独特的方式识别Addition个实例。
您知道,如果来自一个operandOne实例的operandTwoAddition与来自另一个operandOne实例的operandTwoAddition匹配,那么它就足够了认为他们是等于。

hashcode()方法中,它是一回事。