2017-05-05 4 views
2

Je voudrais créer une vue immuable sur la somme d'un nombre (> 2) de multisets Gava immuables. Les multisets sont dans une liste. Je ne veux pas copier le contenu dans un nouveau multiset. Je pourrais probablement utiliser Multisets.sum(Multiset, Multiset) et réduire mon flux de Multisets avec, mais il semble un peu inutile de créer un multiset additionné pour chaque étape intermédiaire. Y a-t-il un meilleur moyen? En d'autres termes: Je veux une méthode similaire à Multisets.sum(Multiset, Multiset), mais pour une liste de multisets au lieu de deux. La signature pourrait être: <T> Multiset<T> sum(List<Multiset<T>>).Fusionner plusieurs multisets goyaves en un seul

+0

pouvez-vous donner un exemple? – notionquest

+0

@notionquest J'ai une 'Liste >' et je veux un 'Multiset 'immuable soutenu par ces multisets, où ils sont combinés de la même manière que' Multisets.sum (Multiset, Multiset) '. Ce n'est pas vraiment un exemple, j'espère que cela clarifie ma question. – Rinke

+0

Vous pouvez envisager de créer un problème sur https://github.com/google/guava/issues pour suggérer l'ajout de 'Multisets.sum (Multiset ...)'. – mfulton26

Répondre

2

En fait, Multisets.sum(Multiset, Multiset) est implémenté de la façon dont il ne copie pas le contenu mais crée plutôt une vue sur deux multisets, donc dans votre cas en boucle sur la liste des multisets et en ne copiant que le résultat final vers un nouveau multiset immuable. t pour petit nombre de multisets). Utilisation de Java 8, vous pouvez combiner sum de Multiset avec Stream#reduce:

public <T> Multiset<T> sum(final List<Multiset<T>> multisets) 
{ 
    return multisets.stream().reduce(ImmutableMultiset.of(), Multisets::sum); 
} 

EDIT

Cependant, bien qu'il n'y aura pas de copie impliqué dans l'approche ci-dessus, comme solution @LouisWasserman note (YMMV) optimale pourrait être juste accumuler les résultats dans une nouvelle multiset:

public <T> ImmutableMultiset<T> sum(final List<Multiset<T>> multisets) 
{ 
    final ImmutableMultiset.Builder<T> builder = ImmutableMultiset.builder(); 
    multisets.forEach(builder::addAll); 
    return builder.build(); 
} 

Avoir classe vue dédiée (voir @ réponse de OliverGregoire) est également une option si nécessaire.

+0

Oui, mais cela ne créerait-il pas beaucoup de multisets intermédiaires pendant la réduction? Le multiset final serait essentiellement un grand arbre de tous ces multisets. Cela semble gaspiller. Qu'est-ce que tu penses? – Rinke

+0

Création d'une classe de vue est bon marché et pour la liste d'entrée de taille <100 (j'ai inventé ce nombre), il ne devrait pas importer et serait un IMO d'optimisation prématurée. * Si * vous voulez optimiser ici, faites des benchmarks et faites le profil de votre code en premier. Avoir une plus petite base de code et réutiliser des goodies de bibliothèque est un plus grand gain pour moi que de créer encore une autre classe (que vous devez maintenir) pour une tâche très étroite. – Xaerxess

+0

Merci. Points raisonnables. En fait, je l'avais déjà implémenté de la même manière que vous le suggérez, mais j'étais toujours curieux de savoir s'il y avait une meilleure solution. – Rinke

4

Il n'y a pas de méthodes qui font cela hors de la boîte. Cependant, rappelez-vous que Guava est sous licence Apache License afin que vous puissiez regarder et réutiliser le code (à condition de respecter les conditions de licence).

La source est disponible here.

Avec cela à l'esprit, vous pouvez créer votre propre classe, une structure similaire à Multisets.sum(Multiset,Multiset) de Goyave:

public class SummedMultiset<T> extends AbstractMultiset<T> { 
    private final ImmutableList<Multiset<T>> multisets; 
    public SummedMultiset(List<Multiset<T>> multisets) { 
    this.multisets = ImmutableList.copyOf(multisets); 
    } 
    @Override public int count(Object element) { 
    return multisets.stream().mapToInt(m -> m.count(element)).sum(); 
    } 
    // Fill all the other methods seen in Guava's source. 
} 

Bien sûr, vous pouvez cacher que la mise en œuvre derrière une méthode:

public class MoreMultisets { 
    public static Multiset<T> sum(List<Multiset<T>> multisets) { 
    return new SummedMultiset<>(multisets); 
    } 
}