Encontre os principais elementos de um multiset do Google Collections?
Pergunta
UMA Coleções do Google Multiset é um conjunto de elementos, cada um dos quais tem uma contagem (ou seja, pode estar presente várias vezes).
Não posso te dizer quantas vezes quero fazer o seguinte
- Faça um histograma (exatamente multiset)
- Obtenha os n elementos principais da contagem do histograma
Exemplos: os 10 principais URLs (por # Times mencionados), 10 principais tags (por # Times aplicados), ...
Qual é a maneira canônica de fazer nº 2, dada a um multiset do Google Collections?
Aqui é um post sobre isso, mas esse código não é exatamente o que eu quero. Primeiro, ele retorna tudo, não apenas o primeiro N. segundo, copia (é possível evitar uma cópia?). Terceiro, eu geralmente quero um tipo determinístico, ou seja, o tiebreak se as contagens forem iguais. Outras linhas: não é estática, etc.
Solução
Escrevi métodos com a funcionalidade básica que você está solicitando, exceto que eles executam cópias e não têm lógica determinística de quebra de ligação. Atualmente, eles são internos para o Google, mas podemos inicializar-os em algum momento. Esta goiaba questão tem as assinaturas de método.
O algoritmo deles é semelhante ao post do blog: classificando uma lista de entradas. Seria mais rápido, mas mais complicado, usar um melhor Algoritmo de seleção.
Editar: desde a goiaba 11, isso é implementado
Outras dicas
Para dar outra perspectiva para as pessoas comentarem, postarei uma versão ligeiramente modificada da postagem do blog que me referente a:
package com.blueshiftlab.twitterstream.summarytools;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multiset;
import com.google.common.collect.Ordering;
import com.google.common.collect.Multiset.Entry;
public class Multisets {
// Don't construct one
private Multisets() {
}
public static <T> ImmutableList<Entry<T>> sortedByCount(Multiset<T> multiset) {
Ordering<Multiset.Entry<T>> countComp = new Ordering<Multiset.Entry<T>>() {
public int compare(Multiset.Entry<T> e1, Multiset.Entry<T> e2) {
return e2.getCount() - e1.getCount();
}
};
return countComp.immutableSortedCopy(multiset.entrySet());
}
public static <T> ImmutableList<Entry<T>> topByCount(Multiset<T> multiset,
int max) {
ImmutableList<Entry<T>> sortedByCount = sortedByCount(multiset);
if (sortedByCount.size() > max) {
sortedByCount = sortedByCount.subList(0, max);
}
return sortedByCount;
}
}