[英]Overwriting the hashCode() and equals() method in Java
正如标题所暗示的那样,我的问题与覆盖 hashCode() 和 equals() 方法有关。 然而,这也不完全正确,我只是不知道用另一种方式来总结我的问题。
我有一个包含多个组件的对象Label
,其中一个是包含多个Node
类型对象的List
。 Label
一个例子是: [(n1, n2, n3), (n4, n5)]
。 我想存储在LinkedHashSet
生成的所有唯一Label
对象。 但是,这并没有按预期工作。 假设LinkedHashSet
当前包含上述Label
,并且我们现在生成了一个名为other
的新Label
,结果证明它包含与已添加标签相同的节点,因此[(n1, n2, n3), (n4, n5)]
。 由于它具有相同的节点列表,因此Label
中的其他组件也相同。 我不会在这里解释为什么,只是假设是这样,因为情况就是这样。 但是,在检查LinkedHashSet
已包含Label
它返回false
,因为对象具有不同的对象 ID。
一种方法是在LinkedHashSet
上编写一个 for 循环,并将新标签与LinkedHashSet
所有标签进行比较,但这在运行时间方面会非常昂贵,所以我正在寻找更便宜的选择。 欢迎任何建议!
另一种方法是调整equals()
方法,但这行不通,因为我还必须调整hashCode()
方法,但我不知道如何更改以使其正常工作。
您绝对不想“对LinkedHashSet
进行 for 循环并进行比较......”检测重复项是LinkedHashSet
应该做的。 为了做到这一点,它需要适当的equals
和hashCode
。
您可能明白您需要实现equals
以便在Label
“等于”另一个Label
时返回 true ,但是您定义了它。 如果两个标签在具有相同节点时相等,那么是的,您几乎必须查看所有节点并检查它们是否相同。
这留下了hashCode
。 您必须实现hashCode
与equals
一致,即如果两个标签相等,则它们必须具有相同的哈希码。 这是因为LinkedHashSet
将使用哈希码来确定Label
所在的桶,然后使用equals
将新Label
与桶中已存在的Label
进行比较。 如果两个标签相等但生成不同的哈希码, LinkedHashSet
将无法将它们检测为重复项。
最简单的做法是将所有节点的哈希码合并到Label
的哈希码中。 就像是:
int hashCode() {
int hc = 1;
for (Node n : allMyNodes) {
hc = hc * 31 + n.hashCode();
}
return hc;
}
如果有很多节点,并且除非它们“相等”,否则两个标签不太可能共享同一个节点,您可以只使用第一个节点的哈希码,而不是翻遍它们。
在这里实现 equals(...) 和 hashCode(...) 是正确的方法。 通常人们使用他们的 IDE 为他们生成这些方法,下面是 Java 7+ 的样子:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Label label = (Label) o;
return Objects.equal(nodes, label.nodes);
}
@Override
public int hashCode() {
return Objects.hashCode(nodes);
}
如果您有多个字段,这将变为:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Label label = (Label) o;
return Objects.equal(nodes, label.nodes) &&
Objects.equal(other, label.other);
}
@Override
public int hashCode() {
return Objects.hashCode(nodes, other);
}
然而,这只有在Node
的实现也实现equals(...)
和hashCode(...)
时才有效。
使用@EqualsAndHashCode
从lombok
,在您的Node
(或Label
)类。
然后您可以将节点添加到您的LinkedHashSet
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.