Jan Nielsen
Jan Nielsen

Reputation: 11799

Java 8 stream: sum of units of same items

Is there a concise way to sum the units of the same type of items in a list with Java 8 streams? For example, suppose I have a list of three items:

{id: 10, units: 1}
{id: 20, units: 2}
{id: 10, units: 1}

I like a summary stream like:

{id: 10, units 2}
{id: 20, units 2}

which sums the units of items of the same id. Any ideas?


Here's Federico's solution (with Lombok):

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


public class So44348207 {

    public static void main(String[] args) {
        List<Item> items = Arrays.asList(
            new Item(10,1), new Item(20,2), new Item(10, 1)
        );

        Map<Long, Integer> results = items.stream().collect(
            Collectors.toMap(
                Item::getId,
                Item::getUnits,
                Integer::sum
                )
            );

        results.forEach( (k,v) -> System.out.println(
            String.format("{id: %d, units: %d}", k,v))
        );
    }

    @Data
    @AllArgsContructor
    public static class Item {
        Long id;
        Integer units;
    }
}

which correctly produces:

java So44348207 
{id: 20, units: 2}
{id: 10, units: 2}

Upvotes: 4

Views: 1745

Answers (2)

user_3380739
user_3380739

Reputation: 1254

Here is another simple solution by StreamEx

StreamEx.of(items).toMap(Item::getId, Item::getUnits, Integer::sum);

Upvotes: 1

fps
fps

Reputation: 34460

Assuming​ you have a class MyClass that encapsulates both fields and has getters for them, you could do it as follows:

Map<Long, Integer> result = list.stream()
    .collect(Collectors.toMap(
        MyClass::getId,
        MyClass::getUnits,
        Integer::sum));

I'm also assuming that id is of type long or Long and units of type int or Integer.

Collectors.toMap creates a map whose keys are determined by its first argument, which is a function that maps an element of the stream to the key of the map. The second argument is a function that maps an element of the stream to the value of the map, and the third argument is an operator that merges two values when there are collisions on the key.

Upvotes: 5

Related Questions