Groupe par et la somme des objets, comme dans SQL avec Java lambdas?
J'ai une classe Foo
avec ces champs:
id:int /nom;String /targetCost:BigDecimal /actualCost:BigDecimal
- Je obtenir une liste de tableaux, d'objets de cette classe. par exemple:
new Foo(1, "P1", 300, 400),
new Foo(2, "P2", 600, 400),
new Foo(3, "P3", 30, 20),
new Foo(3, "P3", 70, 20),
new Foo(1, "P1", 360, 40),
new Foo(4, "P4", 320, 200),
new Foo(4, "P4", 500, 900)
J'ai envie de transformer ces valeurs en créant une somme de "targetCost" et "actualCost" et de regroupement de la "ligne" par exemple
new Foo(1, "P1", 660, 440),
new Foo(2, "P2", 600, 400),
new Foo(3, "P3", 100, 40),
new Foo(4, "P4", 820, 1100)
Ce que j'ai écrit maintenant:
data.stream()
.???
.collect(Collectors.groupingBy(PlannedProjectPOJO::getId));
Comment puis-je le faire?
OriginalL'auteur haisi | 2014-10-13
Vous devez vous connecter pour publier un commentaire.
À l'aide de
Collectors.groupingBy
approche est la bonne, mais au lieu d'utiliser la version à un seul argument qui permettra de créer une liste de tous les éléments, pour chaque groupe, vous devez utiliser les deux arg version qui prend une autreCollector
qui détermine la façon de regrouper les éléments de chaque groupe.Cela est particulièrement lisse, quand vous voulez agréger une seule propriété des éléments ou tout simplement compter le nombre d'éléments par groupe:
De comptage:
Résumant une propriété:
Dans votre cas lorsque vous voulez agréger plus d'une propriété, la spécification d'une réduction personnalisés opération comme suggéré dans cette réponse est la bonne approche, vous pouvez toutefois effectuer la réduction du droit au cours de l'opération de regroupement, donc il n'est pas nécessaire de recueillir l'ensemble des données dans un
Map<…,List>
avant d'effectuer la réduction:(Je suppose que vous utilisez un
import static java.util.stream.Collectors.*;
maintenant...)Pour être complet, voici une solution pour un problème au-delà de la portée de votre question: que faire si vous voulez
GROUP BY
plusieurs colonnes/propriétés?La première chose qui saute dans l'programmeurs de l'esprit, est d'utiliser
groupingBy
pour extraire les propriétés du flux d'éléments et de créer ou de renvoyer un nouvel objet clé. Mais cela nécessite un titulaire de classe pour les propriétés de clé (et Java n'a pas d'usage général Tuple de la classe).Mais il existe une alternative. À l'aide de la trois-arg forme
groupingBy
nous pouvons spécifier un fournisseur pour leMap
de mise en œuvre qui permettra de déterminer la clé de l'égalité. À l'aide d'un triées de la carte avec un comparateur comparant plusieurs propriétés que nous obtenir le comportement souhaité, sans la nécessité d'une classe supplémentaire. Nous n'avons qu'à prendre soin de ne pas utiliser les propriétés de la clé, les instances de notre comparateur ignoré, comme ils l'ont juste des valeurs arbitraires:Collectors
. Que devrait être la réponse acceptéeComment le faire en Java 7, s'il vous plaît ?
c'est une question entièrement différente
c'est bien maintenant, je l'ai déjà fait, mais à l'aide de
Maps
Étape 1: mise à jour de Java 8, étape 2: le profit
OriginalL'auteur Holger
Ici est une approche possible :
De sortie :
reduce((f1,f2) -> { f1.targetCost += f2.targetCost; f1.actualCost += f2.actualCost; return f1;})
travail?La règle générale lors de l'utilisation fonctionnelle de style, c'est que les fonctions doivent être pur, ce qui signifie, sans aucun effet secondaire. La création d'une nouvelle référence a chaque fois un petit coût, ce qui devrait être négligeable pour la grande majorité des applications. Si vous êtes vraiment préoccupé par la performance, ne pas utiliser de cours d'eau comme ils introduisent une surcharge par rapport à une simple boucle.
Merci @Dici. Après avoir lu un peu plus sur ce sujet, j'ai trouvé que le stream().collect() au lieu de (flux).réduire() c'est que je ne veux pas lancer un nouvel objet sur chaque iterateion. Cet article est très utile pour understaning collect(): javabrahman.com/java-8/...
OriginalL'auteur Dici
suffit d'utiliser toMap(), très simple
OriginalL'auteur user1241671
De le faire avec le JDK de
Stream
API uniquement n'est pas vraiment simple comme d'autres réponses ont montré. Cet article explique comment vous pouvez obtenir le code SQL de la sémantique deGROUP BY
en Java 8 (avec les fonctions d'agrégation standard) et en utilisant jOOλ, une bibliothèque qui s'étendStream
pour ces cas d'utilisation.Écrire:
Appel
Sera alors de rendement
OriginalL'auteur Lukas Eder
OriginalL'auteur Shylock.Gou