虽然我磕磕绊绊地找到了这个非常有趣的程序,它允许向HashSet
添加重复的元素。我希望有人可以很好地解释
public class Human implements Comparable<Human> {
Integer age;
public Human(int age) {
this.age = age;
}
public int compareTo(Human h) {
return h.age.compareTo(this.age);
}
public String toString() {
return ""+this.age;
}
}
主要课程
public class Test {
public static void main(String[] args) {
Set<Human> humans = new HashSet<Human>();
humans.add(new Human(13));
humans.add(new Human(33));
humans.add(new Human(21));
humans.add(new Human(21));
System.out.println("Size : "+humans.size());
System.out.print(humans);
}
}
预期输出:[21, 33, 13]
取而代之的是:[21, 21, 33, 13]
答案 0 :(得分:7)
你的类没有实现#hashCode
也没有#equals
- 没有实现HashMap的实现合同(以及HashSet,因为它在内部由HashMap支持)。
http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
由于您的元素使用Object.hashCode()
/ equals()
,因此不考虑对象字段的值,唯一真正重要的是对象的内存地址[因为它是唯一没有明确hashCode()
/ equals()
]区分对象的东西。
在使用基于散列的解决方案时,定义比较器不会帮助 - 它仅适用于已排序的集合。
作为旁注:如果是您的代码,这实际上是好 - 您是否期望两个年龄相同的人是一个人?在这种情况下使用HashXXX的原因对我来说是不清楚的 - 它没有任何好处。在这种特殊情况下的ArrayList ......
编辑:如果你完全确定你想要那种奇怪的行为 - 只需提供
public int hashCode() {
return age;
}
public boolean equals( Object obj ) {
if (this == obj)
return true;
if ( !(obj instanceof Human) ) // null check included for free ^_~
return false;
return age == ((Human)obj).age;
}