Le moyen le plus simple d’itérer à travers un multiset dans l’ordre de la fréquence des éléments?

Prenons cet exemple qui affiche certaines statistiques de type de périphérique. (“DeviceType” est une énumération avec une douzaine de valeurs.)

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

Quelle est la manière la plus simple et la plus élégante d’imprimer les éléments distincts dans l’ordre de leur fréquence (type le plus commun en premier)?

En Multiset un coup d’œil à l’interface Multiset , il n’ya pas de méthode prête à l’emploi pour cela, et aucune des implémentations Multiset de Guava ( HashMultiset , TreeMultiset , etc.) ne semble garder les éléments ordonnés automatiquement.

    Je viens d’append cette fonctionnalité à Guava, voir ici pour le Javadoc.

    Edit : exemple d’utilisation de Multisets.copyHighestCountFirst() selon la question d’origine:

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

    Voici une méthode qui renvoie une List d’entrées, sortingées par fréquence ( UPDATE : utilise un drapeau pour basculer en ordre croissant / décroissant et utilise le jouet préféré de Guava: le Enum Singleton Pattern , comme dans Java effectif , élément 3):

     private enum EntryComp implements Comparator>{ 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  List> getEnsortingesSortedByFrequency( final Multiset ms, final boolean ascending){ final List> entryList = Lists.newArrayList(ms.entrySet()); Collections.sort(entryList, ascending ? EntryComp.ASCENDING : EntryComp.DESCENDING); return entryList; } 

    Code de test:

     final Multiset ms = HashMultiset.create(Arrays.asList( "One", "Two", "Two", "Three", "Three", "Three", "Four", "Four", "Four", "Four" )); System.out.println("ascending:"); for(final Entry entry : getEnsortingesSortedByFrequency(ms, true)){ System.out.println(MessageFormat.format("{0} ({1})", entry.getElement(), entry.getCount())); } System.out.println("descending:"); for(final Entry entry : getEnsortingesSortedByFrequency(ms, false)){ System.out.println(MessageFormat.format("{0} ({1})", entry.getElement(), entry.getCount())); } 

    Sortie:

    Ascendant:
    Un 1)
    Deux (2)
    Trois (3)
    Quatre (4)
    descendant:
    Quatre (4)
    Trois (3)
    Deux (2)
    Un 1)

    Une implémentation utilisant ForwardingMultiSet :

    ( EntryComp de la réponse du sécheur )

     enum EntryComp implements Comparator> { 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 extends ForwardingMultiset { Multiset delegate; EntryComp comp; public FreqSortMultiSet(Multiset delegate, boolean ascending) { this.delegate = delegate; if (ascending) this.comp = EntryComp.ASCENDING; else this.comp = EntryComp.DESCENDING; } @Override protected Multiset delegate() { return delegate; } @Override public Set> entrySet() { TreeSet> sortedEntrySet = new TreeSet>(comp); sortedEntrySet.addAll(delegate.entrySet()); return sortedEntrySet; } @Override public Set elementSet() { Set sortedEntrySet = new LinkedHashSet(); for (Entry en : entrySet()) sortedEntrySet.add(en.getElement()); return sortedEntrySet; } public static  FreqSortMultiSet create(boolean ascending) { return new FreqSortMultiSet(HashMultiset. create(), ascending); } /* * For Testing * public static void main(Ssortingng[] args) { Multiset s = FreqSortMultiSet.create(false); s.add("Hello"); s.add("Hello"); s.setCount("World", 3); s.setCount("Bye", 5); System.out.println(s.entrySet()); }*/ } 

    Comme il n’est pas encore implémenté , je suppose que vous pouvez créer une Map avec key = type et value = count. Puis sortinger cette carte – voir ici