繁体   English   中英

覆盖 Java 中的 hashCode() 和 equals() 方法

[英]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应该做的。 为了做到这一点,它需要适当的equalshashCode

您可能明白您需要实现equals以便在Label “等于”另一个Label时返回 true ,但是您定义了它。 如果两个标签在具有相同节点时相等,那么是的,您几乎必须查看所有节点并检查它们是否相同。

这留下了hashCode 您必须实现hashCodeequals一致,即如果两个标签相等,则它们必须具有相同的哈希码。 这是因为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(...)时才有效。

使用@EqualsAndHashCodelombok ,在您的Node (或Label )类。

然后您可以将节点添加到您的LinkedHashSet

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM