2011-10-24 55 views
6

如果我有Guava Multimap,我將如何根據給定鍵值的數量對條目進行排序?按值的數量排序番石榴Multimap

例如:

Multimap<String, String> multiMap = ArrayListMultimap.create(); 
multiMap.put("foo", "1"); 
multiMap.put("bar", "2"); 
multiMap.put("bar", "3"); 
multiMap.put("bar", "99"); 

鑑於此,遍歷Multimap之時,我將如何獲得「欄」項來第一次(因爲「bar」的有3個值與只有1個「富」 )?

回答

13

提取條目列表,然後對列表進行排序:

List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(map.entries()); 
Collections.sort(entries, new Comparator<Map.Entry<String, String>>() { 
    @Override 
    public int compare(Map.Entry<String, String> e1, Map.Entry<String, String> e2) { 
     return Ints.compare(map.get(e2.getKey()).size(), map.get(e1.getKey()).size()); 
    } 
}); 

然後在項目迭代。

編輯:

如果在內部地圖(Entry<String, Collection<String>>)的條目,你想要的東西,其實是迭代,然後執行以下操作:

List<Map.Entry<String, Collection<String>>> entries = 
    new ArrayList<Map.Entry<String, Collection<String>>>(map.asMap().entrySet()); 
Collections.sort(entries, new Comparator<Map.Entry<String, Collection<String>>>() { 
    @Override 
    public int compare(Map.Entry<String, Collection<String>> e1, 
         Map.Entry<String, Collection<String>> e2) { 
     return Ints.compare(e2.getValue().size(), e1.getValue().size()); 
    } 
}); 

// and now iterate 
for (Map.Entry<String, Collection<String>> entry : entries) { 
    System.out.println("Key = " + entry.getKey()); 
    for (String value : entry.getValue()) { 
     System.out.println(" Value = " + value); 
    } 
} 
+0

謝謝。這將單獨對條目進行排序,但現在我不再有Multimap,只是Map.Entry對象的列表。所以我失去了對單個鍵值的分組。我想要的是保持Multimap,但只是重新排序元素,以便它們按照值的數量降序排列。 –

+0

你說你想迭代條目。你有一個條目列表。迭代這些條目。 MultiMap仍然存在,未觸及。 MultiMap沒有排序,當然也不是按給定鍵值的數量。 –

+0

對不起,我原來的問題不太清楚。我想能夠遍歷原始的Multimap,但是首先獲得最高的計數條目。此外,TreeMultimap對鍵(和值)進行了排序,所以說沒有對Multimap進行排序並不一定準確。 –

8

我會使用Multimap之的keys Multiset項,按降頻排序(一旦將issue 356中描述的功能添加到Guava中,將更容易),並通過遍歷排序的鍵,從原始Multimap中獲取值來構建新的Multimap:

/** 
* @return a {@link Multimap} whose entries are sorted by descending frequency 
*/ 
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) { 
    // ImmutableMultimap.Builder preserves key/value order 
    ImmutableMultimap.Builder<String, String> result = ImmutableMultimap.builder(); 
    for (Multiset.Entry<String> entry : DESCENDING_COUNT_ORDERING.sortedCopy(multimap.keys().entrySet())) { 
     result.putAll(entry.getElement(), multimap.get(entry.getElement())); 
    } 
    return result.build(); 
} 

/** 
* An {@link Ordering} that orders {@link Multiset.Entry Multiset entries} by ascending count. 
*/ 
private static final Ordering<Multiset.Entry<?>> ASCENDING_COUNT_ORDERING = new Ordering<Multiset.Entry<?>>() { 
    @Override 
    public int compare(Multiset.Entry<?> left, Multiset.Entry<?> right) { 
     return Ints.compare(left.getCount(), right.getCount()); 
    } 
}; 

/** 
* An {@link Ordering} that orders {@link Multiset.Entry Multiset entries} by descending count. 
*/ 
private static final Ordering<Multiset.Entry<?>> DESCENDING_COUNT_ORDERING = ASCENDING_COUNT_ORDERING.reverse(); 

編輯:這不工作,如果某些條目具有相同的頻率(見我的評論)

另一種方法,使用基於屈德寧鍵多集的訂購,並ImmutableMultimap.Builder.orderKeysBy()

/** 
* @return a {@link Multimap} whose entries are sorted by descending frequency 
*/ 
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) { 
    return ImmutableMultimap.<String, String>builder() 
      .orderKeysBy(descendingCountOrdering(multimap.keys())) 
      .putAll(multimap) 
      .build(); 
} 

private static Ordering<String> descendingCountOrdering(final Multiset<String> multiset) { 
    return new Ordering<String>() { 
     @Override 
     public int compare(String left, String right) { 
      return Ints.compare(multiset.count(left), multiset.count(right)); 
     } 
    }; 
} 

第二種方法更短,但我不喜歡Ordering具有狀態(取決於Multimap的關鍵Multiset來比較鍵)的事實。

+3

謝謝!第一種方法很好,正是我想要的。儘管第二種方法出了問題(還沒有調試它來弄清楚什麼......但是用我的測試數據,我從一個輸入Multimap開始,其asMap()的大小爲432,但輸出Multimap的asMap()大小隻有21. –

+0

這確實很奇怪,我會在我能找到一些時間的時候測試它,我可能犯了一個錯誤,你確定你沒有比較inputMultimap.size()和outputMultimap.asMap()。size ()? –

+0

正確,我在比較asMap()。size()。 –