2014-07-08 62 views
-5

虽然绊倒我发现这个非常有趣的程序,允许添加重复元素到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]

+4

哈希散列哈希散列。哈希散列哈希。散列哈希。哈希。 –

+0

程序中的'toString()'实现应该是'this.age.toString()'。在这里使用'“”+连接并不理想。 – Unihedron

+1

[Missing something HashSet duplicates]可能的重复(http://stackoverflow.com/questions/1663506/missing-something-hashset-duplicates) – vaxquis

回答

7

你的类没有实现也不#equals - 没有HashMap(和HashSet的实现合同,因为它是backe d通过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; 
} 
+0

据我了解,这样排序的集合包括'TreeSet's? – Unihedron

+0

@Unihedron yup。 TreeSet需要Comparator(实现或明确传递),否则它使用元素的自然排序。 – vaxquis