我知道(合同)我们需要在重写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的定义是“所有字段必须相同”。有了这个,我相信我的代码工作正常,我只发现性能问题。请指出我错在哪里。谢谢
答案 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方法确实非常重要。