Les différences entre les Collectionneurs.toMap() et des Collectionneurs.groupingBy() pour recueillir une partie de la Carte
Je veux créer un Map
à partir d'un List
de Point
s et ont à l'intérieur de la carte toutes les entrées de la liste mappé avec le même parentId comme Map<Long, List<Point>>
.
J'ai utilisé Collectors.toMap()
mais il ne compile pas :
Map<Long, List<Point>> pointByParentId = chargePoints.stream()
.collect(Collectors.toMap(Point::getParentId, c -> c));
Il semble que vous êtes à la recherche pour
Je suis d'accord avec LouisWasserman 'interprétation de la question, mais vous devriez être plus clair dans votre question. Fournir un exemple d'entrée et de sortie , ou même un un Minimum, Complètes et Vérifiables Exemple.
Collectors.groupingBy
.Je suis d'accord avec LouisWasserman 'interprétation de la question, mais vous devriez être plus clair dans votre question. Fournir un exemple d'entrée et de sortie , ou même un un Minimum, Complètes et Vérifiables Exemple.
OriginalL'auteur Tim Schwalbe | 2017-07-21
Vous devez vous connecter pour publier un commentaire.
TLDR :
De recueillir dans un
Map
qui contient une seule valeur par clé (Map<MyKey,MyObject>
), l'utilisationCollectionneurs.toMap()
.Pour recueillir dans un
Map
qui contient plusieurs valeurs par clé (Map<MyKey, List<MyObject>>
), l'utilisationCollectionneurs.groupingBy()
.Collectionneurs.toMap()
Par écrit :
L'objet retourné sera le
Map<Long,Point>
type.Regardez les
Collectors.toMap()
la fonction que vous utilisez :Elle renvoie une
Collector
avec comme résultatMap<K,U>
oùK
etU
sont le type de retour de deux fonctions passés à la méthode.Dans votre cas,
Point::getParentId
est une Longue etc
se réfère à unPoint
.Alors que la
Map<Long,Point>
retourné lorsquecollect()
est appliquée.Et ce comportement est plutôt attendu que Des collectionneurs.toMap() javadoc états :
Mais si les touches repérées contient des doublons (selon
Object.equals(Object)
), unIllegalStateException
est jetéIl sera probablement votre cas comme vous pourrez le groupe de la
Point
s selon une propriété spécifique :parentId
.Si les touches repérées peuvent avoir des doublons, vous pouvez utiliser le
toMap(fonction, Fonction, BinaryOperator)
surcharge, mais il ne sera pas vraiment à résoudre votre problème car il ne sera pas des éléments du groupe avec le mêmeparentId
. Il sera juste fournir un moyen de ne pas avoir deux éléments avec le mêmeparentId
.Collectionneurs.groupingBy()
Pour atteindre votre condition, vous devez utiliser
Collectionneurs.groupingBy()
dont le comportement et la déclaration de la méthode convient beaucoup mieux à votre besoin :Il est précisé que :
La méthode prend un
Function
.Dans votre cas, le
Function
paramètre estPoint
(letype
de Flux), et vous retournezPoint.getParentId()
que vous souhaitez grouper les éléments parparentId
valeurs.De sorte que vous pourriez écrire :
Ou avec une méthode de référence :
Collectionneurs.groupingBy() : aller plus loin
En effet, le
groupingBy()
collecteur va plus loin que l'exemple réel.Le
Collectors.groupingBy(Function<? super T, ? extends K> classifier)
méthode est finalement juste une méthode pratique pour stocker les valeurs de la collecte desMap
dans unList
.Pour stocker des valeurs de la
Map
dans autre chose qu'unList
ou pour stocker le résultat d'un calcul spécifique ,groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
devrait vous intéresser.Par exemple :
Donc au-delà de la question posée, vous devriez envisager de
groupingBy()
comme un moyen souple de choisir des valeurs que vous souhaitez stocker dans le collectéesMap
, ce définitivementtoMap()
ne l'est pas.Autour de la recherche d'informations sur toMap()! Dire bonjour!
OriginalL'auteur davidxxx
Collectors.groupingBy
est exactement ce que vous voulez, il crée une Carte à partir de votre collection d'entrée, la création d'une Entrée à l'aide de laFunction
vous fournir pour cela est la clé, et une Liste de Points clés associés comme la valeur.OriginalL'auteur Patrick
Le code suivant fait les choses.
Collectors.toList()
est celui par défaut, de sorte que vous pouvez ignorer, mais dans le cas où vous voulez avoirMap<Long, Set<Point>>
Collectors.toSet()
serait nécessaire.OriginalL'auteur xenteros
Il est tout à fait vrai que souvent une carte de l'objet.domaine de la Collecte d'objets qui partagent ce champ est mieux stockées dans une Multimap (Goyave a une belle mise en œuvre pour un multi-table).
Si vous n'avez pas BESOIN de le multimap être mutable (ce qui devrait être le cas idéal), vous pouvez utiliser
Si vous devez utiliser une mutable carte, vous pouvez mettre en place un collecteur (comme démontré ici: https://blog.jayway.com/2014/09/29/java-8-collector-for-gauvas-linkedhashmultimap/) ou l'utilisation d'une boucle for (ou forEach) pour remplir un vide, mutable multimap.
Une multimap offre des fonctionnalités supplémentaires que vous devez normalement lorsque vous utilisez une carte de terrain pour la collecte d'objets partageant un champ (comme le nombre total d'objets).
Une mutable multimap rend également plus facile d'ajouter et de supprimer des éléments de la carte (sans être concerné par les cas de bord).
OriginalL'auteur Roy Shahaf