2010-06-12 18 views
13

Un Google CollectionsMultiset est un ensemble d'éléments dont chacun a un compte (c'est-à-dire peut être présent plusieurs fois).Trouver les N éléments principaux dans un multiset de Google Collections?

Je ne peux pas vous dire combien de fois je veux faire ce qui suit

  1. Faire un histogramme (exactement Multiset)
  2. Obtenez les éléments supérieurs de N par comptage de l'histogramme

Exemples: top 10 URL (par # fois mentionné), top 10 tags (par # fois appliqué), ...

Quelle est la manière canonique de faire # 2 avec un multi-collection Google Collections?

Here est un article de blog à ce sujet, mais ce code n'est pas tout à fait ce que je veux. D'abord, il renvoie tout, pas seulement le top N. Deuxièmement, il copie (est-il possible d'éviter une copie?). Troisièmement, je veux généralement un tri déterministe, c'est-à-dire un jeu décisif si les comptes sont égaux. D'autres nits: ce n'est pas statique, etc.

Répondre

4

je l'ai écrit méthodes avec le fonctionnalité de base que vous demandez, sauf qu'ils effectuent des copies et manquent de logique déterministe. Ils sont actuellement internes à Google, mais nous pouvons les ouvrir à un moment donné. Ce goyavier issue a les signatures de méthode.

Leur algorithme est similaire au blog: tri d'une liste d'entrées. Il serait plus rapide, mais plus compliqué, d'utiliser un meilleur selection algorithm.

EDIT: depuis 11 goyave, c'est implemented

+0

comment l'utiliser pour obtenir les N meilleurs éléments? –

3

Pour donner une autre perspective pour les gens de commenter, je posterai une version légèrement modifiée du blog I VISÉES:

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

Si je comprends bien, cette solution copier et de trier la collection chaque fois que vous voulez récupérer les premiers éléments de N. Je ne sais pas exactement quelles sont vos exigences, mais la solution de tri de tas bat cela à la fois dans le temps et dans l'espace, donc je ne suis pas sûr de ce que l'avantage est. – danben

+0

Vous optimisez pour la vitesse, je cherche le moins # de lignes de code écrites par moi. – dfrankow

+0

Je vois - ce n'était pas clair à partir de votre poste, d'autant plus que vous avez demandé d'éviter de faire une copie. – danben