HashSet允许添加重复元素

时间:2014-07-08 16:29:01

标签: java hashset

虽然我磕磕绊绊地找到了这个非常有趣的程序,它允许向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]

1 个答案:

答案 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;
}