2011-12-16 107 views
1

我有hashmap<CustomObject,Integer>,我想比較每個條目中的整數(值)。所以,基本上我想按降序排列我的值Integer的值。我有一個Comparator它由以下部分組成...將HashMap與對象比較

class Compare implements Comparator<Integer>{ 
    Map<CustomObject,Integer> map; 
    /** 
    * Constructs our map 
    * @param map map to be sorted. 
    */ 
    public Compare(Map<CustomObject,Integer> map){ 
     this.map = map; 
    } 
    /** 
    * Performs the comparison between two entries. 
    */ 
    public int compare(Integer one, Integer two){ 
     if(map.get(one) <= map.get(two)){ 
      return 1; 
     }else{ 
      return 0; 
     } 
    } 
} 

我通過我的Hashmap成樹形圖通過調用下面的代碼行.. Tmap.putAll(Hmap);。凡TMAP和HMAP被定義爲:當我運行我的代碼

private HashMap<CustomObject,Integer> Hmap; 
private TreeMap<CustomObject,Integer> Tmap; 

我得到的錯誤Exception in thread "main" java.lang.ClassCastException: CustomObject cannot be cast to java.lang.Comparable

當我試圖從我的排序列表中提取一個值時,異常似乎會被調用。像這樣......

TreeMap<CustomObject,Integer> sorted = Tmap.putAll(hmap); 
sorted.get(o); 

其中o是CustomObject。

我想我誤解了比較器的工作原理..我做錯了什麼?我如何比較兩個整數值?

編輯

只是爲了澄清什麼,我實際上是試圖做...

我想比較其鏈接到CustomObject整數。我無法使整數的關鍵,因爲這些整數可能不是唯一的。我想對它們進行比較,因爲我想根據它們的Integer值以降序對我的集合進行排序。

+0

哪裏是拋出異常的代碼? – SJuan76 2011-12-16 12:50:07

+0

問題是比較器的地圖比較鍵而不是值。除了執行反向映射外,我沒有看到任何解決方案,然後繼續,然後將結果插入到LinkedHashMap中。不是你想要的,我希望... – fge 2011-12-16 12:52:02

回答

5

你需要改變你的比較來比較CustomObject S,不Integers

class Compare implements Comparator<CustomObject>{ 
    Map<CustomObject,Integer> map; 
    /** 
    * Constructs our map 
    * @param map map to be sorted. 
    */ 
    public Compare(Map<CustomObject,Integer> map){ 
     this.map = map; 
    } 
    /** 
    * Performs the comparison between two entries. 
    */ 
    public int compare(CustomObject left, CustomObject right){ 
     return map.get(left).compareTo(map.get(right)); 
    } 
} 

然後,你需要告訴TreeMap使用您的比較:

private Map<CustomObject,Integer> Tmap = 
    new TreeMap<CustomObject,Integer>(new Compare(HMap)); 
0

第一薄的是,鍵應該是Integer,值應該是CustomObject,然後可以根據比較器對HashMap進行排序。但默認情況下HashMap的,或者如果你婉排序CustomObject那麼你必須做出CustomObject實現可比譜寫比較方法,這將使HashMap的排序基於CustomObject。如果你已經理解了這一點。並想嘗試你的自我嘗試。或者如果你想讓我解釋一個例子,我可以做到這一點。

問題很混亂。

1
new TreeMap<..>(new Compare<..>(map)) 

您必須在構建樹時指定比較器。否則,它假設你的鑰匙是可比的(他們並不)

check this answer進行排序基於值的地圖。

1

這種方法有一些問題。

  • TreeMap忽略重複項(當compareTo返回0時)在你的情況下,它只會增加遞減遞減的整數值。您可以修復它,以便數字可以按任意順序排列,但它仍會刪除具有重複值的任何條目。
  • compareTo中使用的字段不能更改或將損壞集合。
  • 您需要知道整個密鑰才能查找值。在這種情況下,您需要知道在這種情況下的值,以查看它可能不是非常有用的。

您是關創建從map.entrySet(),您可以排序List<Entry<CustomObject,Integer>>更好,因爲這允許重複並且是有序的。

1

我認爲問題在於您使用的是錯誤的TreeMap構造函數。您正在使用的那個要求所有密鑰都是實現Comparable的類的實例。您的CustomObject沒有。您應該使用帶有Comparator參數的構造函數;例如

TreeMap<CustomObject,Integer> tmap = 
    new TreeMap<CustomObject,Integer>(new Compare()); 

這也將告訴你,你的比較類需要實現Comparator<CustomObject>Comparator<Integer>

另一個問題是你的比較器沒有實現正確的語義。如果arg1 < arg2,比較方法應該返回一個-ve數字,如果arg1 = arg2則返回零,如果arg1> arg2則返回一個+ ve數字;例如

public int compare(CustomObject one, CustomObject two){ 
    return Integer.compare(map.get(one), map.get(two)); 
} 

即使這是狡猾的:

  • 如果映射到相同的整數任何兩個CustomObject情況下,將被視爲平等的,你就不能兼得的(不同)鍵在TreeMap中。

  • 如果map中沒有輸入onetwo,那麼您的比較器將拋出NPE。

1

我會建議使用由整數索引的多圖。如果您需要保留按對象查找這些對的功能,則可以維護這兩個映射。 Java沒有提供multimap,但有一些簡單的解決方案。 HereMap<Integer,List<Object>>的示例(向下滾動到multimaps部分)。