userei keys Multiset voci del Multimap, ordinali in base alla frequenza decrescente (che sarà più facile quando la funzionalità descritta in issue 356 viene aggiunta a Guava) e costruisci un nuovo Multimap ripetendo le chiavi ordinate, ottenendo i valori dalla Multimap originale:
/**
* @return a {@link Multimap} whose entries are sorted by descending frequency
*/
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) {
// ImmutableMultimap.Builder preserves key/value order
ImmutableMultimap.Builder<String, String> result = ImmutableMultimap.builder();
for (Multiset.Entry<String> 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<Multiset.Entry<?>> ASCENDING_COUNT_ORDERING = new Ordering<Multiset.Entry<?>>() {
@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<Multiset.Entry<?>> DESCENDING_COUNT_ORDERING = ASCENDING_COUNT_ORDERING.reverse();
EDIT: QUESTO NON FUNZIONA Se alcune voci hanno la stessa frequenza (vedi il mio commento)
Un altro approccio, utilizzando un ordinamento in base ai Multimaps' chiavi Multiset, e ImmutableMultimap.Builder.orderKeysBy():
/**
* @return a {@link Multimap} whose entries are sorted by descending frequency
*/
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) {
return ImmutableMultimap.<String, String>builder()
.orderKeysBy(descendingCountOrdering(multimap.keys()))
.putAll(multimap)
.build();
}
private static Ordering<String> descendingCountOrdering(final Multiset<String> multiset) {
return new Ordering<String>() {
@Override
public int compare(String left, String right) {
return Ints.compare(multiset.count(left), multiset.count(right));
}
};
}
Il secondo approccio è più breve, ma non mi piace il fatto che l'ordine abbia uno stato (dipende dalla chiave Multiset della Multimap per confrontare le chiavi).
fonte
2011-10-24 21:49:56
Grazie. Questo ordinerà le voci individualmente, ma ora non ho più un Multimap, solo una lista di oggetti Map.Entry. Quindi ho perso il raggruppamento di valori in una singola chiave. Quello che voglio è mantenere il Multimap, ma riordinare semplicemente gli elementi in modo che siano in ordine decrescente in base al numero di valori. –
Hai detto che volevi scorrere le voci. Hai una lista di voci. Scorri sopra queste voci. Il MultiMap è ancora lì, intatto. Una MultiMap non è ordinata, e certamente non dal numero di valori per una data chiave. –
Scusa, la mia domanda iniziale non era abbastanza chiara. Voglio essere in grado di scorrere il Multimap originale, ma ottenere le voci di conteggio più alte prima. Inoltre, un TreeMultimap ha ordinato chiavi (e valori), quindi non è necessariamente esatto dire che un Multimap non è ordinato. –