【问题标题】:Java HashSet using customized class as key: "contains()" function always return false使用自定义类作为键的 Java HashSet:“contains()”函数总是返回 false
【发布时间】:2019-05-12 09:03:25
【问题描述】:

我正在尝试使用 HashSet,同时使用我自己的类“Inner”作为键类型,如下所示:

import java.util.HashSet;
class Inner {
    int i;
    String s;
    public Inner(int i, String s) {
        this.i = i;
        this.s = s;
    }
    @Override
    public int hashCode() {
        return super.hashCode();
    }
    @Override
    public boolean equals(Object o) {
        Inner inner = (Inner) o;
        return i == inner.i && s.equals(inner.s);
    }
}

public class testEquals {
    public static void main(String [] args) {
        HashSet<Inner> hi = new HashSet<>();
        hi.add(new Inner(1,"abc"));
        System.out.println(hi.contains(new Inner(1,"abc")));
    }
}

它打印“假”

(1) 我的问题是,只要我尝试使用“contains”函数,我必须从“Inner”类构造一个新对象来查询,但是因为它是一个新对象,所以 hashcode() 是不同的。所以我总是得到一个“错误”的“包含”功能。

(2) 如果我将 hashCode() 更改为在值相同时返回“true”,就像等于一样,那么在其他情况下,不同的对象引用被视为“==”,就像一个唯一的引用一样。

(1)和(2)似乎冲突。

如何解决?

谢谢!

【问题讨论】:

    标签: java key equals hashset hashcode


    【解决方案1】:

    您应该覆盖hashCode,使两个相等的对象具有相同的hashCode

    例如:

    @Override
    public int hashCode() {
        return Objects.hash(i,s);
    }
    

    我不确定 (2) 有什么问题。如果两个对象根据equals() 相等,则HashSet 应该将它们视为相同的对象,即使它们不是。

    另一方面,如果您希望HashSet 将任何Inner 实例视为唯一的(无论其实例变量的值如何),请不要覆盖hashCodeequals。但是,在不覆盖这些方法的情况下使用 HashSet 很少有用。

    【讨论】:

      【解决方案2】:
      1. 您必须正确覆盖 hashCode() 而不会破坏 equals - hashcode 合约。

      equals() 和 hashCode() 之间的约定是:

      1. 如果两个对象相等,则它们必须具有相同的哈希码。
      2. 如果两个对象具有相同的哈希码,它们可能相等也可能不相等。
      1. hashCode() 不返回 true,它返回一个 int 值。因此,只需确保它为 equals() 返回 true 的 2 个不同对象返回相同的 int 值。

      【讨论】:

        猜你喜欢
        • 2019-02-18
        • 1970-01-01
        • 2020-04-19
        • 2021-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多