una recorrer objetos listas lista iterar imprimir elemento ejemplo java guava multiset

java - recorrer - ¿La forma más simple de iterar a través de un Multiset en el orden de frecuencia de los elementos?



recorrer arraylist java foreach (4)

Considere este ejemplo que imprime algunas estadísticas de tipo de dispositivo. ("DeviceType" es una enumeración con una docena de valores).

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

¿Cuál es la manera más simple y elegante de imprimir los distintos elementos en el orden de su frecuencia (primero el tipo más común)?

Con una mirada rápida a la interfaz de Multiset , no hay un método ya hecho para esto, y ninguna de las implementaciones de Multiset de Guava ( HashMultiset , TreeMultiset , etc.) parece mantener automáticamente los elementos ordenados por frecuencia.


Acabo de agregar esta característica a Guava, mire here para ver el Javadoc.

Editar : ejemplo de uso de Multisets.copyHighestCountFirst() según la pregunta original:

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


Aquí hay un método que devuelve una List de entradas, ordenadas por frecuencia ( ACTUALIZACIÓN : utilizó una bandera para alternar orden ascendente / descendente y usó el juguete favorito de Guava: el Enum Singleton Pattern , como se encuentra en Java efectivo , punto 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; }

Código de prueba:

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

Salida:

Ascendente:
Uno 1)
Dos (2)
Tres (3)
Cuatro (4)
descendiendo:
Cuatro (4)
Tres (3)
Dos (2)
Uno 1)



Una implementación que usa ForwardingMultiSet :

( EntryComp de seanizer''s answer de seanizer''s )

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