Search code examples
javacollectionsjava-streamgroupingcollectors

Java: construct a map aggregating its value if key is present


I have a list of GroupItem objects:

public class GroupItem {
    Group group;
    BigDecimal value;
    ...
}

What I want to achieve is a Map where value for the same Group key is aggregated. I implemented it in the following way (slightly refactored variant, but still far from being elegant):

List<GroupItem> items = generateGroupItemList();

Map<Group, BigDecimal> resultMap = new HashMap<>();
    for (GroupItem item : items) {
        resultMap.put(item.getGroup(), resultMap.getOrDefault(item.getGroup(), BigDecimal.ZERO).add(item.getValue()));
    }

This variant looks ugly and lacks readability. I tried using streams, but didn't achieve any positive result. The general idea was around Collectors.groupingBy() and something like this:

items.stream().collect(
        Collectors.groupingBy(
                GroupItem::getGroup,
                Collectors.reducing(GroupItem:getValue, /*BigDecimal::add*/)
));

Is there more elegant way to achieve desired effect, besides the variant above?


Solution

  • Using Stream, you can perform toMap with Collectors:

    Map<Group, BigDecimal> resultMap = items.stream()
            .collect(Collectors.toMap(GroupItem::getGroup,
                    GroupItem::getValue, BigDecimal::add));