Java HashSet 使用自定义 class 作为键:"contains()" function always return false

Java HashSet using customized class as key: "contains()" function always return false

我正在尝试使用 HashSet,同时使用我自己的 class "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")));
    }
}

它打印 "false"

(1) 我的问题是,只要我尝试使用"contains"函数,我就必须从"Inner" class构造一个新的对象来查询,但是因为它是一个新对象, hashcode() 是不同的。所以我总是得到 "false" 的 "contains" 函数。

(2) 如果我把 hashCode() 改成 return "true" 就像当值相同时等于,那么在其他情况下,不同的对象引用被认为是“==”而已就像一个独特的参考。

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

如何解决?

谢谢!

您应该重写 hashCode,使两个相同的对象具有相同的 hashCode

例如:

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

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

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

  1. 您必须在不破坏 equals - 哈希码约定的情况下正确覆盖 hashCode()

The contract between equals() and hashCode() is:

  1. If two objects are equal, then they must have the same hash code.
  2. If two objects have the same hash code, they may or may not be equal.
  1. hashCode() 不 return 是真的,它 return 是一个 int 值。因此,只需确保 return 两个不同对象的相同 int 值 equals() return 为真。