I have some trouble finding a good approach/implementation using the Stream API for the following:
I have a list of elements, each element consisting of a string and an integer. Now I like to group the elements by their string values, and then for each group I like to have the sum of the integer values from the elements that relate to that group.
Example: I have the following 3 elements:
("GroupA", 100) ("GroupA", 50) ("GroupB", 10)
And as a result I like to get a map consisting of the following two (key,value) pairs:
("GroupA, 150) ("GroupB, 10)
I'm not sure how to solve this. The most promising I came up with so far is this:
elements.stream().collect(Collectors.groupingBy(e-> e.getGroup()))
.merge(group, elementsOfTheGroup, (...));
But I'm not sure what function to insert as the last parameter of the merge method. But I don't know if I should even use the merge method.
What would be the most elegant implementation for this?
You need to add a downstream collector to Collectors.groupingBy(classifier, downstream)
. This collectors collects all elements that were classified to the same key. In this case, we just need to sum all the numbers together using Collectors.summingInt(mapper)
, with the mapper being a function returning the number to sum.
Assuming this number can be retrieved with the getter getNumber()
, you could have:
Map<String, Integer> result =
elements.stream().collect(Collectors.groupingBy(
e -> e.getGroup(),
Collectors.summingInt(e -> e.getNumber())
));
You could use a method-reference instead of the two lambdas above. If the class of the elements is Element
for example, you would have
Map<String, Integer> result =
elements.stream().collect(Collectors.groupingBy(
Element::getGroup,
Collectors.summingInt(Element::getNumber)
));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With