Java中Hashset出现这种奇怪行为的原因是什么? [重复]

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

我在弄乱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并且哈希码相同,重复项仍然保留。

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

java equals hashset hashcode
1个回答
5
投票

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查看为Dogs

最后一点:Java中的常规约定是用单数形式命名类,除非出于某些原因认为每个实例将包含多个对象。这是为了避免歧义。 Dog d清楚d是什么;显然是Dog。什么是Dogs dd是否有很多狗,而它们只是没有自己的对象类型?它变得有点模棱两可。

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