数据成员在重写hashcode和equals时要考虑

时间:2014-10-20 02:28:59

标签: java equals hashcode

我知道(合同)我们需要在重写equals时覆盖hashcode。 为什么我应该将用于equals比较的相同字段视为计算哈希码? 是否通过避免过多的对象映射到同一个桶来提高性能,如下面的情况? 即在同一个“日期”创建的所有对象都将映射到同一个存储桶,并且使用equals()方法检查对象存在时,线性比较会花费时间吗?

如果我的上述陈述属实,那么除了性能问题之外,代码下面会出现其他潜在问题。这是我们应该使用equals中使用的相同字段/成员来计算哈希码的唯一原因吗?请分享。谢谢。

class MyClass {
  int date;
  int pay;
  int id;

  public boolean equals(Object o) {
    //null and same class instance check
    MyClass obj = (MyClass) o;
    return (date == obj.date && pay == obj.pay && id == obj.id);
  }

  public int hashCode() {
    int hash = 7;
    return (31 * hash + date);
  }
}

//请原谅语法错误,我输入时不使用ide。

***我的意图是使用equals中的所有字段,并知道为什么在hashcode中应该使用相同数量的元素,如果只使用少量元素会发生什么

澄清: 只使用“日期”来计算哈希码,指针检查右桶地址(你同意吗?)此外,我得到该桶中的项目列表,集合将迭代以检查是否存在使用equals的特定obj。我对equals的定义是“所有字段必须相同”。有了这个,我相信我的代码工作正常,我只发现性能问题。请指出我错在哪里。谢谢

2 个答案:

答案 0 :(得分:1)

对于您的示例,我建议您仅使用id来表示相等性,并注释它们是否会覆盖。另外,我想覆盖toString()

@Override
public boolean equals(Object o) {
  if (o instanceof MyClass) {
    return (id == ((MyClass) o).id);
  }
  return false;
}

@Override
public int hashCode() {
  return id;
}

@Override
public String toString() {
  return String.format("MyClass (id=%d, date=%d, pay=%d)", id, date, pay);
}

这样您就可以更新date和/或pay,而无需重新创建哈希结构。此外,这似乎是关于实例的独特之处。

答案 1 :(得分:0)

我在Effective Java中找到了答案,Joshua Bloch,第二版,第49页“不要试图从哈希码计算中排除对象的重要部分以提高性能”。质量差可能会降低哈希表的性能。

所以我的猜测是正确的,多个哈希将映射到同一个桶。

其他信息: http://www.javaranch.com/journal/2002/10/equalhash.html

  

由于类成员/变量num和data确实参与了   等于方法比较,他们也应该参与   计算哈希码。 虽然,这不是强制性的。你可以   使用参与equals方法的变量子集   比较以提高hashCode方法的性能。性能   hashCode方法确实非常重要。