有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java以元素频率顺序遍历多集的最简单方法?

考虑这个例子,打印出一些设备类型统计信息。(“DeviceType”是具有dozenish值的枚举。)

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

按频率顺序打印不同元素的最简单、最优雅的方法是什么(最常见的类型优先)

快速查看一下^{}接口,没有现成的方法,而且Guava的Multiset实现(HashMultisetTreeMultiset等)似乎也没有自动保持元素的频率顺序


共 (4) 个答案

  1. # 1 楼答案

    我刚刚在番石榴中添加了这个特性,请参见here了解Javadoc

    编辑:根据原始问题Multisets.copyHighestCountFirst()的用法示例:

    Multiset<DeviceType> histogram = getDeviceStats();
    for (DeviceType type : Multisets.copyHighestCountFirst(histogram).elementSet()) {
        System.out.println(type + ": " + histogram.count(type));
    }
    
  2. # 2 楼答案

    使用ForwardingMultiSet的实现:

    EntryComp来自seanizer'sanswer

    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());
        }*/
    
    }
    
  3. # 3 楼答案

    下面是一个返回List条目的方法,按频率排序(更新:使用一个标志切换升序/降序,并使用番石榴最喜欢的玩具:Enum Singleton Pattern,如Effective Java,第3项所示):

    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;
    }
    

    测试代码:

    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()));
    }
    

    输出:

    ascending:
    One (1)
    Two (2)
    Three (3)
    Four (4)
    descending:
    Four (4)
    Three (3)
    Two (2)
    One (1)

  4. # 4 楼答案

    因为it is not yet implemented,我想你可以创建一个Map,key=type,value=count。然后对地图进行排序——参见here