2014-02-24 81 views
0

我目前有一個安裝程序,其中數據結構是ArrayList,每個鍵包含ArrayList中每個鍵的HashMap。我想要做的是能夠通過HashMap本身內的鍵或鍵進行排序。在我的研究中,大部分的建議似乎是使用Collections.sort(ArrayList,comparatorFunction()),然後構建一個自定義的Comparator函數來完成排序,但作爲一個完整的noob如何構建一個比較器...我不'甚至不知道從哪裏開始,更不用說構建一個'我敢肯定不是一個簡單的設置。任何碰巧知道某些資源對於解決這種功能都很有用的方法?通過嵌套的HashMap中的多個鍵排序

編輯:對不起,一些示例結構將有所幫助。

如果你調用了arrayList.get(0)並對它做了一個System.out.println,它會返回說{鎮=多倫多,人口= 2,500,000,年齡= 147},我想要做的是有它,所以我可以說人口排序ArrayList,然後例如年齡。

+0

[如何使用比較器接口](http://stackoverflow.com/questions/16126563/how-to-use-the-comparator-interface) – mazaneicha

+2

*「一個ArrayList,每個鍵包含一個HashMap對於ArrayList中的每個鍵「* ArrayList沒有鍵,所以......你是什麼意思?你能舉一個例子說明這些是如何聲明的以及你想要排序的嗎? – Radiodef

回答

1

通常在這種情況下,比較器的工作是簡單地從其他東西返回一個比較值。例如,這裏是一個比較會按字母順序排列的字體:

class FontAlphabetizer 
implements Comparator<Font> { 
    @Override 
    public int compare(Font font1, Font font2) { 
     return font1.getName().compareTo(font2.getName()); 
    } 
} 

這實際上是非常簡單的:getName返回一個字符串而我們要做的就是返回字符串的方法compareTo的價值。

在這裏它看起來像你所擁有的是ArrayList<Map>,你想根據Map中的選定值對ArrayList進行排序。所以你需要的是一個Comparator<Map>。您需要爲比較器提供您想要排序的相應值的關鍵字。這可以表示一般像下面這樣:

class MapValueComparator<K, V extends Comparable<V>> 
implements Comparator<Map<K, V>> { 
    final K key; 

    MapValueComparator(K key) { 
     this.key = key; 
    } 

    @Override 
    public int compare(Map<K, V> map1, Map<K, V> map2) { 
     return map1.get(key).compareTo(map2.get(key)); 
    } 
} 

這是比較地圖比較器和它在聲明中指定有該地圖的價值觀也必須是可比的。它根據從給定密鑰中檢索的值進行比較。

因此,舉例來說,如果我們有一個ArrayList<Map<String, String>>,我們可以通過值從"town"排序是這樣的:

static void sortByTown(List<Map<String, String>> list) { 
    Collections.sort(list, new MapValueComparator<String, String>("town")); 
} 

,打嗝是,你說你有town=Toronto, population=2,500,000這表明人口要排序是一個字符串(因爲它可能與多倫多在相同的地圖中)。作爲字符串可能是不希望的,因爲它會按字典順序排序(50進入250萬之後,因爲5自帶2後)比較人口。在這種情況下通用版本可能無法工作,因爲你需要採取的值轉換爲數字的一個額外的步驟。

class PopulationComparator 
implements Comparator<Map<String, String>> { 
    @Override 
    public int compare(Map<String, String> map1, Map<String, String> map2) { 
     final Long pop1 = Long.valueOf(map1.get("population")); 
     final Long pop2 = Long.valueOf(map2.get("population")); 

     return pop1.compareTo(pop2); 
    } 
} 

(而作爲一個側面說明,如果你的羣體包括你需要它解析爲數字前將其格式化。您可以使用replaceAll("\\D", "")從字符串中刪除所有非數字的逗號。)

這也是一種情況,爲此創建一個類而不是使用Map可能會有好處。那麼你可以讓數字字段爲數字類型。如果你有一堂課,比較將大致相同,只是返回一個選定字段的比較。

1

自定義比較器可用於定義您的類的對象可以比較的方式。它的語法如下:

public class CustomComparator implements Comparator<MyObjectType> 
{ 
    public int compare(MyObjectType ob1 , MyObjectType ob2) 
    { 
    //code to compare the 2 objects 
    } 
} 

請參考以下鏈接的信息,在收集要素的自定義排序創建一個比較類:link

1

這裏是你在找什麼:

final List<Map<String, Object>> towns = new ArrayList<Map<String, Object>>(); 

final Map<String, Object> toronto = new HashMap<String, Object>(); 
toronto.put("town", "Toronto"); 
toronto.put("population", 2500000); 
toronto.put("age", 147); 
towns.add(toronto); 

final Map<String, Object> ottawa = new HashMap<String, Object>(); 
ottawa.put("town", "Ottawa"); 
ottawa.put("population", 883000); 
ottawa.put("age", 159); 
towns.add(ottawa); 

final Map<String, Object> montreal = new HashMap<String, Object>(); 
montreal.put("town", "Montreal"); 
montreal.put("population", 1600000); 
montreal.put("age", 372); 
towns.add(montreal); 

final Map<String, Object> quebec = new HashMap<String, Object>(); 
quebec.put("town", "Quebec City"); 
quebec.put("population", 600000); 
quebec.put("age", 406); 
towns.add(quebec); 

final Map<String, Object> vancouver = new HashMap<String, Object>(); 
vancouver.put("town", "Vancouver"); 
vancouver.put("population", 600000); 
vancouver.put("age", 128); 
towns.add(vancouver); 

Collections.sort(towns, new Comparator<Map<String, Object>>() { 
    @Override 
    public int compare(final Map<String, Object> o1, final Map<String, Object> o2) { 
     if (o1.get("population") instanceof Integer && o2.get("population") instanceof Integer && !((Integer)o1.get("population")).equals((Integer)o2.get("population"))) { 
      return ((Integer)o1.get("population")).compareTo((Integer)o2.get("population")); 
     } 
     if (o1.get("age") instanceof Integer && o2.get("age") instanceof Integer) { 
      return ((Integer)o1.get("age")).compareTo((Integer)o2.get("age")); 
     } 
     // Default if there is no population/no age, shouldn't happen. 
     // TODO : do something else. 
     return o1.toString().compareTo(o2.toString()); 
    } 
}); 

for (final Map<String, Object> town: towns) { 
    System.out.println(town.get("population")+"\t"+town.get("age")+"\t"+town.get("town")); 
} 

代碼的第一部分是根據您所說的創建ArrayList,然後我們使用自定義ComparatorList進行排序,並打印結果。

這裏是輸出:

600000 128 Vancouver 
600000 406 Quebec City 
883000 159 Ottawa 
1600000 372 Montreal 
2500000 147 Toronto 

正如你所看到的,它是由人口排序,然後按年齡。

但是,也許是最好的解決辦法是創建一個對象Town,有三個字段(name,​​和age),並使用這個對象,而不是HashMap秒。