【问题标题】:Java: construct a map aggregating its value if key is presentJava:如果存在键,则构造一个聚合其值的映射
【发布时间】:2020-03-11 21:35:21
【问题描述】:

我有一个 GroupItem 对象列表:

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

我想要实现的是一个 Map,其中聚合了相同 Group 键的值。我通过以下方式实现它(稍微重构的变体,但仍然远非优雅):

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


【解决方案1】:

使用Stream,可以执行toMapCollectors

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

【讨论】:

  • 作为一种流方法,它是一种非常紧凑且不错的解决方案。我忘了 Collectors.toMap() 有 BinaryOperator arg 用于合并。
【解决方案2】:

你可以使用merge方法:

  List<GroupItem> items = generateGroupItemList();

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

【讨论】:

  • 我将问题中的示例更改为单行且不那么丑陋,但仍远非理想。你的回答使它完美。谢谢。
猜你喜欢
  • 2022-12-05
  • 2013-08-26
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 2018-11-15
  • 2021-09-14
  • 1970-01-01
  • 2021-05-01
相关资源
最近更新 更多