You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java8 Stream如何按ID和日期分组并合并订单金额?

简化同ID同日期订单金额合并的实现

需求说明

需要将订单列表中相同ID且相同日期的订单金额合并,最终返回合并后的Order列表,而非Map结构。

原实现的问题

原代码通过两次嵌套分组(先按ID分组,再按日期分组),再循环合并结果,步骤繁琐且不够直观。

简化实现方案

可以直接使用复合分组键(将ID和日期组合为唯一键),配合Collectors的分组与合并工具,一步完成分组、合并与结果转换。

方案1:基于自定义Collector的实现

利用AbstractMap.SimpleEntry作为复合分组键,结合自定义Collector合并订单:

import java.util.AbstractMap;
import java.util.List;
import java.util.stream.Collectors;

// 保留原Order类的accept和combine方法
List<Order> mergedOrders = orders.stream()
    // 按ID+日期的复合键分组
    .collect(Collectors.groupingBy(
        order -> new AbstractMap.SimpleEntry<>(order.getId(), order.getDate()),
        // 自定义Collector:创建新Order并合并金额
        Collector.of(
            Order::new,
            Order::accept,
            Order::combine
        )
    ))
    // 提取分组后的合并结果,转为List
    .values()
    .stream()
    .collect(Collectors.toList());

方案2:基于reducing的更简洁实现

优化Order类,添加纯函数式的合并方法,配合Collectors.reducing简化代码:

首先修改Order类,添加静态合并方法(避免修改原对象的副作用):

import java.time.LocalDate;

public class Order {
    private Integer id;
    private LocalDate date;
    private double amount;

    // 自行补充构造方法、getter、setter

    // 纯函数式合并:返回新订单,不修改原对象
    public static Order merge(Order order1, Order order2) {
        Order merged = new Order();
        merged.setId(order1.getId());
        merged.setDate(order1.getDate());
        merged.setAmount(order1.getAmount() + order2.getAmount());
        return merged;
    }
}

然后使用reducing完成合并:

List<Order> mergedOrders = orders.stream()
    .collect(Collectors.groupingBy(
        order -> new AbstractMap.SimpleEntry<>(order.getId(), order.getDate()),
        // 使用reducing合并同组订单
        Collectors.reducing(new Order(), Order::merge)
    ))
    .values()
    .stream()
    .collect(Collectors.toList());

方案优势

  • 一步完成分组与合并,代码简洁直观
  • 避免嵌套循环与中间Map的繁琐处理
  • 纯函数式的合并方法(方案2)无副作用,更安全可靠

内容的提问来源于stack exchange,提问作者Knowhen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:30:35