HashSet允许添加重复元素

Spa*_*kOn -5 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

主要课程

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);
    }

    }
Run Code Online (Sandbox Code Playgroud)

预期产出: [21, 33, 13]

取而代之的是: [21, 21, 33, 13]

vax*_*uis 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;
}
Run Code Online (Sandbox Code Playgroud)