java - Java 中的 Hashset 出现这种奇怪行为的原因是什么?

标签 java equals hashset hashcode

我一直在尝试理解 HashSet 的行为方式,但遇到了这个我无法理解的问题。第二个和第三个狗对象具有相同的名称,并且 equals()hashcode()已被覆盖以使名称意味着平等。尽管如此,hashSet 仍然有重复项,我不明白为什么。

我重读了 Head First Java 的数据结构章节,但它仍然表明我的代码理论上应该可以工作。

public class DataStructsTests<E> {

HashSet<Dogs> tree = new HashSet<Dogs>();
HashSet<Dogs> treeOwner = new HashSet<Dogs>();

public static void main(String[] args) {
    DataStructsTests<String> d = new DataStructsTests<String>();
    d.go();
}

public void go() {
    Dogs dog = new Dogs("Scout", "a");
    tree.add(dog);
    treeOwner.add(dog);

    Dogs dog2 = new Dogs("Brodie", "b");
    tree.add(dog2);
    treeOwner.add(dog2);

    Dogs dog3 = new Dogs("Brodie", "c");
    tree.add(dog3);
    treeOwner.add(dog3);

    System.out.println(tree);
    System.out.println(treeOwner);

    System.out.println(dog2.equals(dog3));
    System.out.println(dog2.hashCode() + " " + dog3.hashCode());
}

class Dogs {
    private String name;
    private String ownerName;

    public Dogs(String n, String o) {
        name = n;
        ownerName = o;
    }

    public boolean equals(Dogs d) {
        return name.equals(d.getName());
    }

    public int hashCode() {
        return name.hashCode();
    }

         public String getName() {
        return name;
    }

             public String toString() {
        return name;
    }

运行程序返回:

[Brodie, Brodie, Scout]
[Brodie, Brodie, Scout]
true
1998211617 1998211617

尽管equals()返回 true 并且哈希码相同,重复项仍然存在。

编辑:原来问题是我没有正确重写 equals() 方法,因为我使用的是 Dog 而不是 Object。

最佳答案

equals 采用 Object 类型的对象,该对象由 HashSet 调用。你需要这样的东西:

@Override
public boolean equals(Object d) {
    if (! d instanceof Dogs){
         return false;
    }
    return name.equals(((Dogs) d).getName());
}

以下是该答案的组成部分:

  1. public boolean equals(Object d) - equals,至少从 Object 继承的版本,被定义为采用 Object ,因此要覆盖它,您还必须获取一个 Object
  2. @Override - 如果您犯了像问题中那样的错误,则告诉编译器向您发出警告。
  3. d instanceof Dogs - 首先检查输入的Object是否是Dogs
  4. ((Dogs) d).getName() - 转换为 Dogs 的原因是因为 d 现在正在传入作为 Object,因此您不会自动获得对 Dogs 方法的访问权限,除非您明确表示要将 Object 查看为一只

最后一点:Java 中的一般约定是以单数命名类,除非有某种理由相信每个实例将是多个事物。这是为了避免歧义。 Dog d 明确了 d 是什么;它显然是一只Dogs d 到底是什么? d 狗很多,但它们只是没有自己的对象类型?它变得有点模棱两可。

关于java - Java 中的 Hashset 出现这种奇怪行为的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56429544/

相关文章:

java - 添加到集合时防止重复

Java SSL - 以编程方式将自签名证书添加到 cacerts

java - 如何在 Struts 2 中将两个 boolean 值与 OGNL 连接起来?

java - MenuItem.setIcon 在使用 BottomNavigationBar 时抛出 NullPointerException

java - 在Java中使用==运算符来比较包装对象

Java - 如何知道HashSet已经被淘汰了?

java - 将 XML 数据 "location"解析为 Google map

c# - “包含”方法返回 false

java - 两个相同的字符串不相等(不是指针/引用错误)

java - 如何声明和初始化包含 HashSet 的 HashMap