2015-01-04 45 views
1

我的工作與TreeSet收集用下面的代碼:是什麼平等之間的差異,包含的方法

import java.util.*; 
public class Employee implements Comparable<Employee>{ 

    private int ID; 

    public Employee(int iD) { 
     ID = iD; 
    } 

    @Override 
    public int compareTo(Employee obj) { 
     return this.ID-obj.ID; 
    } 

    private static void intoTreeSet() { 
     Employee e1=new Employee(4); 
     Employee e2=new Employee(2); 
     Employee e3=new Employee(1); 
     Employee e4=new Employee(5); 
     Employee e5=new Employee(3); 

     Employee eTemp=new Employee(3); 

     Set<Employee> set=new TreeSet(); 
     set.add(e1);set.add(e2);set.add(e3);set.add(e4);set.add(e5); 

     System.out.println("output says: "); 
     for(Employee e:set){ 
      System.out.print(e.ID+" ~ "); 
     } 
     System.out.println(); 
     if(set.contains(eTemp)){ 
      System.out.println("C O N T A I N S !!!"); 
     } 

     if(e5.equals(eTemp)){ 
      System.out.println("E Q U A L S !!!"); 
     } 
    } 

    public static void main(String[] args) { 
     intoTreeSet(); 
    } 
} 

輸出

output says: 
1 ~ 2 ~ 3 ~ 4 ~ 5 ~ 
C O N T A I N S !!! 

我很困惑,看看輸出。我想知道,如果它不通過equals的情況下,那麼它怎麼通過contains的情況。

我知道兩個對象只有在它們的類覆蓋equals方法時纔可以相等,並且它們根據某些屬性是相等的。我故意沒有覆蓋equals的方法,看看如何contains工作。如果它是基於非樹的收集可以說一個ArrayList它不會通過contains測試。爲什麼這樣?任何人都可以解釋這種行爲並清除我的困惑。

+3

「一個TreeSet實例使用其compareTo(或compare)方法執行所有元素比較,因此從該方法看,被這個方法視爲相等的兩個元素相等。」 –

+1

來自幾年前的類似問題:http://stackoverflow.com/questions/12761532/equals-and-comparable-with-sets – FoggyDay

+0

http://stackoverflow.com/questions/6476600/ –

回答

3

這裏要記住的最重要的一點是,TreeSetSortedSet,它使用compareTo (or compare)方法執行元素比較。

員工類是可比。根據可比接口文檔的定義,

該接口對每個實現它的類 的對象施加總排序。這種排序被稱爲該類的 自然排序,而該類的compareTo方法被稱爲 其自然比較方法。

因此,如果您compareTo方法返回0,對於同一類的兩個實例,它們被認爲是由TreeSet自然相等。

該文件還稱,

強烈推薦(雖然不是必需的)使自然排序與 等於一致。這是因爲排序集(和排序映射)沒有明確的 比較器行爲「奇怪」時,它們的自然順序與等號不一致的元素(或 鍵)使用。

雖然沒有定義它的行爲有多「奇怪」。

在我們的案例中,e5.equals(eTemp)false,因爲equals方法未被覆蓋。
e5.compareTo(eTemp)true,所以從集合的角度來看e5eTemp是相等的。

爲了證明這一點,你可以執行以下操作:

Employee e1 = new Employee(3); 
Employee e2 = new Employee(3); 
set.add(e1); // gets added to the set 

因爲設置考慮了e2同等已經存在於集合,但e1.equals(e2)false下面的操作將返回false,和集合的大小保持不變。

System.out.println(set.add(e2)); // false 

因此,爲了保持一致,你可以覆蓋equals方法,雖然它是沒有必要的。

+0

哇。這是一個很好的解釋。毫無疑問,沒有混淆,只有更多的知識。謝謝 :) – JPG

6

The javadoc for java.util.TreeSet說:

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

換句話說,compareToequals的實現必須相互一致。如果他們不是,TreeSet的行爲將是不穩定的。它可能工作,它可能不會。要了解它何時以及何時不需要仔細觀察TreeSet的實現,但由於javadoc對TreeSet的工作條件非常明確,因此試圖顛覆它並不是一個好主意。

+0

一個歷史經典。我已經看到至少有50個標籤爲'treeset'的問題,它們基本上提出相同的問題並得到相同的(正確的)答案。我想知道爲什麼這麼多人在詢問之前不在這裏搜索。 ;-) – kriegaex

相關問題