2013-07-12 81 views
2

我試圖在論壇中回答this問題,我發現儘管覆蓋Employee類中的equals方法,但我仍然可以向TreeSet添加重複元素。TreeSet違反設置合同?

TreeSet.add(E)方法的Javadoc說

將指定元素添加到這個組,如果它不是已存在。 更正式地說,如果集合 不包含元素e2使​​得(e == null?e2 == null:e.equals(e2)),則將指定元素e添加到該集合。 如果此集合已包含該元素,則該呼叫將保持集合 不變,並返回false。

這基本上意味着沒有2等於對象將被插入到TreeSet中並且等式僅由equals()確定包含對象的方法。

但是,下面的代碼是增加2元至Set,即使他們是平等的

public class Employee implements Comparable<Employee> { 

    String employeeName; 
    int employeeId; 

    public Employee(String name, int id) { 
     this.employeeName = name; 
     this.employeeId = id; 
    } 

    public int compareTo(Employee emp) { 
     //return this.employeeName.compareTo(emp.employeeName); 
     return (this.employeeId - emp.employeeId); 
    } 

    @Override 
    public String toString() { 
     return ("Name is: " + employeeName + " Emp id is: " + employeeId); 
    } 

    @Override 
    public boolean equals(Object emp) { 
     if(emp instanceof Employee &&((Employee)emp).employeeName.equals(this.employeeName)){ 
      return true; 
     } 
     return false; 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     Set<Employee> set = new TreeSet<Employee>(); 
     Employee e1 = new Employee("A", 1); 
     Employee e2 = new Employee("A", 2); 
     System.out.println(e1.equals(e2)); 
     set.add(e1); 
     set.add(e2); 
     System.out.println(set); 
    } 

} 

,這裏是輸出

true 
[Name is: A Emp id is: 1, Name is: A Emp id is: 2] 

爲什麼TreeSet因此即使他們是多個元素等於?

現在我改變了EmployeecompareTo方法這樣

public int compareTo(Employee emp) { 
    return this.employeeName.compareTo(emp.employeeName); 
} 

,輸出是

true 
[Name is: A Emp id is: 1] 

如何TreeSet覆蓋compareTo後正常工作?

回答

9

TreeSet中的Javadoc,還說:

注意,由一組(無論是否提供了明確的比較器)保持的順序必須是以等於如果是要正確實現一致Set接口。 (對於與equals一致的準確定義見ComparableComparator)。這是因爲該Set接口在equals操作方面被定義,但TreeSet實例執行使用其compareTo(或compare)方法所有元件比較,所以從這個方法看,被這個方法認爲是相等的兩個要素是相等的。即使其排序與等號不一致,集合的行爲也是定義良好;它只是不服從Set接口的總體合同。

我同意,add()的Javadoc可以更清楚地表明equals()沒有實際使用,並重新狀態或連結此警告,雖然。

+0

謝謝你指出正確的javadoc。 – sanbhat

+0

@sanbhat也在'SortedSet'中指定,'TreeSet'實現'SortedSet'。 –

+0

感謝@LuiggiMendoza我最初找不到它......我正在尋找由一組維護的**排序(不管是否提供了明確的比較器)必須與等於一致** – sanbhat

0

Set實現在幕後使用Map來管理數據,並在此過程中通過Map的密鑰保證對象的唯一性。

據我所知,equals沒有明確的測試意味着你的對象將被添加,如果它不是明確的相同的對象(即'==')。

我認爲這些文檔具有誤導性,但我想這是說它是正式的語言表達。這是不明確的,所以我可能是錯的,但我非常肯定,憑藉底層地圖的關鍵,唯一性得到保證。僅供參考:以您的對象爲關鍵值傳遞虛擬值。

+0

這沒有任何做與'Set'的實現。請注意,'TreeSet'實現'NavigableSet'和'SortedSet'(參考[here](http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html))和'SortedSet'聲明使用[自然排序](http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html)(請參考[here](http://docs.oracle.com/) JavaSE的/ 7 /文檔/ API/JAVA/util的/ SortedSet.html))。 –

0

關於TreeSet的第一件事是,它在stroing它們時也維護對象的順序並使用compareTo方法。

因爲在您的compareTo方法的第一個版本中,您正在使用employeeId進行比較,並將對象e1和e2的diffrent emoplyee id。

Treeset會將此視爲不同的對象,因爲比較不會發送零值(它會發送+或 - 值)。

但在第二個版本中,您使用employeeName實現了compareTo,這與對象e1和e2相同。

相關問題