2013-06-06 55 views
0

我有一個簡單的類,其中包含一個字符串(名稱)和一個整數(年齡)。應存儲在集合中的對象不得具有雙重名稱值,並應按照年齡下降進行排序。 第一個代碼示例刪除所有的雙名,但不包含第二排序標準:Java比較器:兩個排序標準

public int compare(Person p1, Person p2) { 
    int reVal = 1; 

     if(p1.getName().compareTo(p2.getName()) != 0){ 
     reVal = 1;  
     } 
     else { 
     reVal = 0;  
     }        
     return reVal;     
    } 

下一個例子比較責令其餘集中的對象的,不包含任何雙名:

public int compare(Person p1, Person p2) { 
    boolean ageGt = (p1.getAge() > p2.getAge()); 
    int reVal = 1; 

     if(p1.getName().compareTo(p2.getName()) != 0){ 
     if(scoreGt) 
      reVal = -1; 
     else 
      reVal = 1;  
     } 
     else { 
     reVal = 0;  
     }        
     return reVal;     
    } 

第二個比較器正確地根據它們的年齡值命令對象,但它允許雙重名稱,我不明白,因爲如果兩個對象的名稱相同,則已經檢查了外部if語句。爲什麼會發生?

+0

雙重名稱是什麼意思? –

+0

@kocko我認爲他的意思是他不能有兩個同名的對象,所以如果他們有相同的名字,他們被認爲是平等的。 – jazzbassrob

+4

「比較器」不是爲了測試唯一性。如果你想測試名稱的唯一性,你應該使用一個'Map'作爲鍵值和人名。 – fge

回答

3

這裏有一個基本問題:您想同時測試唯一性以訂購條目。沒有內置的集合,這將檢查在同一時間的條目都是平等他們比較是0

例如,兩個Set實現是HashSetTreeSet

  • HashSet使用Object' s .equals()/.hashCode()測試是否相等;
  • TreeSet使用Comparator(或對象'Comparable功能,如果他們實現它)來測試相等性。

這是不完全相同的事情。事實上,在一個特定的JDK類,也就是BigDecimal,這可以得到相當令人吃驚:

final BigDecimal one = new BigDecimal("1"); 
final BigDecimal oneDotZero = new BigDecimal("1.0"); 

final Set<BigDecimal> hashSet = new HashSet<>(); 
// BigDecimal implements Comparable of itself, so we can use that 
final Set<BigDecimal> treeSet = new TreeSet<>(); 

hashSet.add(one); 
hashSet.add(oneDotZero); 
// hashSet's size is 2: one.equals(oneDotZero) == false 

treeSet.add(one); 
treeSet.add(oneDotZero); 
// treeSet's size is... 1! one.compareTo(oneDotZero) == 0 

你不能同時有你魚與熊掌兼得。在這裏,您要根據名稱和年齡比較測試unicity,您必須使用Map

至於要獲得排序的人員列表,您將不得不復制該地圖的.values()作爲列表並使用Collections.sort()。如果您使用番石榴,則後一部分與Ordering.natural().sortedCopy(theMap.values())一樣簡單,只要您的值實施Comparable即可。

+0

謝謝。覆蓋對象類的'equals()'方法是不是一個好的選擇?在這種情況下,我只需要在將對象o1添加到集合之前調用'mySet.contains(o1)'。之後,根據等價合同保證唯一性。 – user1812379

+0

如果您重寫'.equals()',則還必須重寫'.hashCode()'!是的,如果你在一個依賴於平等的「集合」中使用這些值,那麼你必須這樣做。 – fge

+0

但'hashCode()'只對基於哈希的集合是必需的,不是嗎?其他人只是忽略它。在這種情況下,name.hashCode()是一個簡單但可行的散列碼嗎?謝謝。 – user1812379