我在弄乱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()方法。
equals
接受类型为Object
的对象,该对象是HashSet
所调用的对象。您需要类似:
@Override
public boolean equals(Object d) {
if (! d instanceof Dogs){
return false;
}
return name.equals(((Dogs) d).getName());
}
此答案的组成部分:
public boolean equals(Object d)
-equals
,至少是从Object
继承的版本,被定义为使用Object
,因此要覆盖它,还必须使用Object
。@Override
-告诉编译器如果您像在问题中一样犯了错误,则会警告您。d instanceof Dogs
-首先检查输入的Object
是否甚至是Dogs
。((Dogs) d).getName()
-强制转换为Dogs
的原因是因为d
现在以Object
的形式传递,因此除非您明确声明,否则您不会自动获得对Dogs
方法的访问权限您想将Object
查看为Dogs
。最后一点:Java中的常规约定是用单数形式命名类,除非出于某些原因认为每个实例将包含多个对象。这是为了避免歧义。 Dog d
清楚d
是什么;显然是Dog
。什么是Dogs d
? d
是否有很多狗,而它们只是没有自己的对象类型?它变得有点模棱两可。