Java 重写哈希代码和相等时要考虑的数据成员
我知道(契约)当覆盖equals时,我们需要覆盖hashcode。 为什么要考虑与计算哈希代码比较相等的相同字段? 它是为了提高性能,避免太多的对象映射到同一个bucket,如下例所示? i、 e.在同一个“日期”创建的所有对象都将映射到同一个bucket,使用equals()方法检查对象是否存在需要时间进行线性比较 如果我的上述说法是正确的,那么除了性能问题之外,下面的代码还有哪些潜在问题。这是我们应该使用equals中使用的相同字段/成员来计算哈希代码的唯一原因吗?请分享。谢谢Java 重写哈希代码和相等时要考虑的数据成员,java,equals,hashcode,Java,Equals,Hashcode,我知道(契约)当覆盖equals时,我们需要覆盖hashcode。 为什么要考虑与计算哈希代码比较相等的相同字段? 它是为了提高性能,避免太多的对象映射到同一个bucket,如下例所示? i、 e.在同一个“日期”创建的所有对象都将映射到同一个bucket,使用equals()方法检查对象是否存在需要时间进行线性比较 如果我的上述说法是正确的,那么除了性能问题之外,下面的代码还有哪些潜在问题。这是我们应该使用equals中使用的相同字段/成员来计算哈希代码的唯一原因吗?请分享。谢谢 class
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中应该使用相同数量的元素,以及如果只使用很少的元素会发生什么 澄清:
由于只使用“date”来计算hashcode,指针会检查正确的bucket地址(您同意吗?),而且,我得到了该bucket中的项目列表,集合将使用equals迭代检查特定的obj是否存在。我对equals的定义是“所有字段必须相同”。有了这个,我相信我的代码工作得很好,我只发现性能问题。请指出我错在哪里。谢谢你的例子,我建议你只使用
id
来表示相等,并说明它们是覆盖。另外,我喜欢覆盖toString()
这样,您就可以更新
日期
和/或支付
,而无需重新创建哈希结构。此外,这也是实例的独特之处。我在Efficient Java中找到了答案,作者Joshua Bloch,第2版edtn,第49页“不要试图从哈希代码计算中排除对象的重要部分以提高性能”。质量差可能会降低哈希表的性能
所以我的猜测是对的,多个散列将映射到同一个bucket
其他信息:
因为类成员/变量num和data确实参与了
等于方法比较,他们也应该参与
哈希代码的计算但是,这不是强制性的。您可以
使用参与equals方法的变量子集
比较以提高hashCode方法的性能。演出
hashCode方法的实现确实非常重要
我的目的是使用equals中的所有字段,并了解为什么hashcode中应该使用相同数量的元素,以及如果只使用很少的元素会发生什么情况。@davidrun是的,我阅读了您的代码。如果您使用了所有元素,并且您的实例不是不可变的,那么在
HashSet
或HashMap
中更改字段将不会像您预期的那样起作用,因为您的实例将更改其相等性,并且hashCode值将与元素分配给的bucket不匹配。Elliott Frish,仅使用“date”为了计算hashcode,指针检查正确的bucket地址(您同意吗?),此外,我得到该bucket中的项目列表,集合将使用equals迭代检查特定的obj是否存在。我对equals的定义是“所有字段必须相同”。有了这一点,我相信我的代码工作得很好,我只发现性能问题。请指出我错在哪里。谢谢。你还必须考虑这个要求(在同一本书的其他地方,Irc中提到),<代码> HASCODE() >与等式一致。基本上,这意味着如果obj1.equals(obj2)
,则obj1
和obj2
必须具有相同的哈希值。反之亦然;如果!obj1.equals(obj2)
而且它们的散列值相同,这实际上并没有错,但基于散列的集合的性能会很差。@KevinKrumwiede,是的,我知道这一点,我的目的是了解代码在以下情况下是否失败:如果在equals()比较中使用了“n”个成员,并且我对散列代码使用了“小于n”个成员,我的代码是否会中断或是什么。但它不会中断,但会增加将多个对象映射到同一个bucket的机会,从而降低性能。谢谢
@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);
}