我在弄乱试图了解HashSets的行为时遇到了麻烦,但遇到了一个我无法理解的问题。第2和第3狗对象具有相同的名称,并且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()方法。
答案 0 :(得分:5)
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
,因此要覆盖它,还必须使用{{ 1}}。Object
-告诉编译器是否警告您,如果您像在问题中一样犯了错误。@Override
-首先检查输入的d instanceof Dogs
甚至是Object
。Dogs
-强制转换为((Dogs) d).getName()
的原因是因为Dogs
现在以d
的形式传递,所以您不会自动获得对{除非您明确表示要将Object
视为Dogs
,否则{1}}的方法。最后一点要注意:Java中的常规约定是用单数形式命名类,除非出于某些原因相信每个实例将包含多个对象。这是为了避免歧义。 Object
清楚说明Dogs
是什么;显然是Dog d
。 d
到底是什么? Dog
是否有很多狗,而它们没有自己的对象类型?变得有点模棱两可。