Java:构造一个映射,如果存在键,则将其值汇总

问题描述 投票:1回答:3

我有一个GroupItem对象的列表:

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

我想实现的是一个地图,其中汇总了相同组键的值。我以以下方式实现(略微重构的变体,但仍然不够优雅):

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()));
    }

此变体看起来很丑,并且缺乏可读性。我尝试使用流,但未取得任何积极成果。总体思路是围绕Collectors.groupingBy()和类似的内容:

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

除了上述变体以外,还有其他更优雅的方法来达到预期的效果吗?

java collections java-stream grouping collectors
3个回答
2
投票

使用Stream,可以用toMap执行Collectors

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

2
投票

您可以使用merge方法:

  List<GroupItem> items = generateGroupItemList();

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

1
投票

您可以使用Collectors.mappingCollectors.collectingAndThen的组合

Map<Group, BigDecimal> res = items.stream()
            .collect(Collectors.groupingBy(GroupItem::getGroup,
                    Collectors.mapping(GroupItem::getValue, 
                      Collectors.collectingAndThen(Collectors.toList(),
                            list -> list.stream().reduce(BigDecimal.ZERO, BigDecimal::add)))));

或更简单地说,您也可以使用computeIfAbsent

for(GroupItem item : items) {
        resultMap.computeIfAbsent(item.getGroup(), k->BigDecimal.ZERO).add(item.getValue());

    }
© www.soinside.com 2019 - 2024. All rights reserved.