以元素频率的顺序迭代Multiset的最简单方法是什么?

问题描述 投票:32回答:4

考虑这个打印出一些设备类型统计数据的例子。 (“DeviceType”是一个带有十二个值的枚举。)

Multiset<DeviceType> histogram = getDeviceStats();
for (DeviceType type : histogram.elementSet()) {
    System.out.println(type + ": " + histogram.count(type));
}

以频率顺序打印不同元素的最简单,最优雅的方法是什么(最常见的类型是第一种)?

快速浏览一下Multiset界面,没有现成的方法,而且Guava的Multiset实现(HashMultisetTreeMultiset等)似乎都不会自动保持按频率排序的元素。

java guava multiset
4个回答
39
投票

我刚刚将此功能添加到Guava中,请参阅Qazxswpoi以获取Javadoc。

编辑:根据原始问题的here的用法示例:

Multisets.copyHighestCountFirst()

7
投票

这是一个返回Multiset<DeviceType> histogram = getDeviceStats(); for (DeviceType type : Multisets.copyHighestCountFirst(histogram).elementSet()) { System.out.println(type + ": " + histogram.count(type)); } 条目的方法,按频率排序(UPDATE:使用一个标志来切换升序/降序并使用Guava最喜欢的玩具:List,如Enum Singleton Pattern,第3项中所示):

Effective Java

测试代码:

private enum EntryComp implements Comparator<Multiset.Entry<?>>{
    DESCENDING{
        @Override
        public int compare(final Entry<?> a, final Entry<?> b){
            return Ints.compare(b.getCount(), a.getCount());
        }
    },
    ASCENDING{
        @Override
        public int compare(final Entry<?> a, final Entry<?> b){
            return Ints.compare(a.getCount(), b.getCount());
        }
    },
}

public static <E> List<Entry<E>> getEntriesSortedByFrequency(
    final Multiset<E> ms, final boolean ascending){
    final List<Entry<E>> entryList = Lists.newArrayList(ms.entrySet());
    Collections.sort(entryList, ascending
        ? EntryComp.ASCENDING
        : EntryComp.DESCENDING);
    return entryList;
}

输出:

上升: 一(1) 二(2) 三(3) 四(4) 降: 四(4) 三(3) 二(2) 一(1)


3
投票

使用final Multiset<String> ms = HashMultiset.create(Arrays.asList( "One", "Two", "Two", "Three", "Three", "Three", "Four", "Four", "Four", "Four" )); System.out.println("ascending:"); for(final Entry<String> entry : getEntriesSortedByFrequency(ms, true)){ System.out.println(MessageFormat.format("{0} ({1})", entry.getElement(), entry.getCount())); } System.out.println("descending:"); for(final Entry<String> entry : getEntriesSortedByFrequency(ms, false)){ System.out.println(MessageFormat.format("{0} ({1})", entry.getElement(), entry.getCount())); } 的实现:

(来自ForwardingMultiSet seanizer's的EntryComp)

answer

2
投票

enum EntryComp implements Comparator<Multiset.Entry<?>> { DESCENDING { @Override public int compare(final Entry<?> a, final Entry<?> b) { return Ints.compare(b.getCount(), a.getCount()); } }, ASCENDING { @Override public int compare(final Entry<?> a, final Entry<?> b) { return Ints.compare(a.getCount(), b.getCount()); } }, } public class FreqSortMultiSet<E> extends ForwardingMultiset<E> { Multiset<E> delegate; EntryComp comp; public FreqSortMultiSet(Multiset<E> delegate, boolean ascending) { this.delegate = delegate; if (ascending) this.comp = EntryComp.ASCENDING; else this.comp = EntryComp.DESCENDING; } @Override protected Multiset<E> delegate() { return delegate; } @Override public Set<Entry<E>> entrySet() { TreeSet<Entry<E>> sortedEntrySet = new TreeSet<Entry<E>>(comp); sortedEntrySet.addAll(delegate.entrySet()); return sortedEntrySet; } @Override public Set<E> elementSet() { Set<E> sortedEntrySet = new LinkedHashSet<E>(); for (Entry<E> en : entrySet()) sortedEntrySet.add(en.getElement()); return sortedEntrySet; } public static <E> FreqSortMultiSet<E> create(boolean ascending) { return new FreqSortMultiSet<E>(HashMultiset.<E> create(), ascending); } /* * For Testing * public static void main(String[] args) { Multiset<String> s = FreqSortMultiSet.create(false); s.add("Hello"); s.add("Hello"); s.setCount("World", 3); s.setCount("Bye", 5); System.out.println(s.entrySet()); }*/ } 开始,我想你可以用key = type和value = count创建一个it is not yet implemented。然后对该地图进行排序 - 请参阅Map

© www.soinside.com 2019 - 2024. All rights reserved.