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

问题描述 投票:1回答:3

正如标题所示,我的问题与覆盖hashCode()和equals()方法有关。但是,这也不是完全正确的,我只是不知道另一种方式来总结我的问题。

我有一个包含多个组件的对象Label,其中一个是List,其中包含多个Node类型的对象。 Label的示例为:[(n1, n2, n3), (n4, n5)]。我想存储在Label中生成的所有唯一LinkedHashSet对象。但是,这不能按预期方式工作。假设LinkedHashSet当前包含上述Label,并且我们现在生成了一个名为Label的新other,结果它包含与已添加标签相同的节点,因此也包含[(n1, n2, n3), (n4, n5)]。由于它具有相同的节点列表,因此Label中的其他组件也相同。我不会在这里解释原因,只是假设是这样,因为是这种情况。但是,在检查LinkedHashSet是否已包含Label时,由于对象具有不同的对象ID,因此它将返回false

一种方法是在LinkedHashSet上编写一个for循环,然后将新标签与LinkedHashSet中的所有标签进行比较,但这在运行时间方面将非常昂贵,因此我希望找到一种更便宜的标签选项。欢迎任何建议!

另一种方法是采用equals()方法,但是没有用,因为我还必须采用hashCode()方法,并且我不知道要进行什么更改才能使它起作用。

java equals contains hashcode
3个回答
1
投票

实现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(...)的情况下,这才起作用。


0
投票

@EqualsAndHashCode(或lombok)类别中使用Node中的Label

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


0
投票

您绝对不希望“循环LinkedHashSet并进行比较...”。检测重复是LinkedHashSet应该做的。为此,它需要equalshashCode的适当实现。

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

留下hashCode。您必须实现hashCodeequals一致,即,如果两个标签相等,则它们必须具有相同的哈希码。这是因为LinkedHashSet将使用哈希码来确定Label所在的存储桶,然后使用equals将新的Label与存储桶中已经存在的存储桶进行比较。如果两个标签相等但生成不同的哈希码,则LinkedHashSet将无法将它们检测为重复。

最简单的方法是将所有节点的哈希码合并到Label的哈希码中。类似于:

int hashCode() {
    int hc = 1;
    for (Node n : allMyNodes) {
        hc = hc * 31 + n.hashCode();
    }
    return hc;
}

[如果有很多节点,并且除非“相等”,否则两个标签不太可能共享同一节点,您可以只使用第一个节点的哈希码,而不是遍历它们。”>

© www.soinside.com 2019 - 2024. All rights reserved.