2014-07-08 94 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