按值数对Guava Multimap进行排序

如果我有一个Guava Multimap,我将如何根据给定密钥的值数对条目进行排序?

例如:

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

鉴于此,当迭代遍历multiMap时,我如何首先获得“bar”条目(因为“bar”有3个值而“foo”只有1个)?

提取列表中的条目,然后对列表进行排序:

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

然后迭代条目。

编辑:

如果你想要的实际上迭代内部映射的条目( Entry> ),那么执行以下操作:

 List>> entries = new ArrayList>>(map.asMap().entrySet()); Collections.sort(entries, new Comparator>>() { @Override public int compare(Map.Entry> e1, Map.Entry> e2) { return Ints.compare(e2.getValue().size(), e1.getValue().size()); } }); // and now iterate for (Map.Entry> entry : entries) { System.out.println("Key = " + entry.getKey()); for (String value : entry.getValue()) { System.out.println(" Value = " + value); } } 

我将使用Multimap的键Multiset条目,按降序频率对它们进行排序(一旦将问题356中描述的function添加到Guava,这将更容易),并通过迭代已排序的键来构建新的Multimap,从原始Multimap获取值:

 /** * @return a {@link Multimap} whose entries are sorted by descending frequency */ public Multimap sortedByDescendingFrequency(Multimap multimap) { // ImmutableMultimap.Builder preserves key/value order ImmutableMultimap.Builder result = ImmutableMultimap.builder(); for (Multiset.Entry 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> ASCENDING_COUNT_ORDERING = new Ordering>() { @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> DESCENDING_COUNT_ORDERING = ASCENDING_COUNT_ORDERING.reverse(); 

编辑:如果某些条目具有相同的频率,这不起作用(请参阅我的评论)

另一种方法,使用基于Multimaps’键Multiset的Ordering和ImmutableMultimap.Builder.orderKeysBy() :

 /** * @return a {@link Multimap} whose entries are sorted by descending frequency */ public Multimap sortedByDescendingFrequency(Multimap multimap) { return ImmutableMultimap.builder() .orderKeysBy(descendingCountOrdering(multimap.keys())) .putAll(multimap) .build(); } private static Ordering descendingCountOrdering(final Multiset multiset) { return new Ordering() { @Override public int compare(String left, String right) { return Ints.compare(multiset.count(left), multiset.count(right)); } }; } 

第二种方法更短,但我不喜欢Ordering具有状态的事实(它取决于Multimap的关键字Multiset比较键​​)。