当前位置: 首页 > news >正文

Java中用Stream流取出分组后每组中最大值对应的对象

Java中用Stream流取出分组后每组中最大值对应的对象

要从分组后的结果中实际取出这些对象(而不是Optional包装的对象),有几种常用的方法:

方法1:直接处理Map中的Optional

Map<String, Optional<Order>> groupedResult = orders.stream()
    .collect(Collectors.groupingBy(
        Order::getCustomerId,
        Collectors.maxBy(Comparator.comparing(Order::getOrderDate))
    ));

// 取出所有对象
List<Order> resultObjects = groupedResult.values().stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

方法2:使用collectingAndThen去除Optional

Map<String, Order> resultMap = orders.stream()
    .collect(Collectors.groupingBy(
        Order::getCustomerId,
        Collectors.collectingAndThen(
            Collectors.maxBy(Comparator.comparing(Order::getOrderDate)),
            opt -> opt.orElse(null)
        )
    ));

// 取出所有非null对象
List<Order> resultObjects = resultMap.values().stream()
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

方法3:直接收集到List(Java 12+)

List<Order> resultObjects = orders.stream()
    .collect(Collectors.groupingBy(
        Order::getCustomerId,
        Collectors.maxBy(Comparator.comparing(Order::getOrderDate))
    ))
    .values().stream()
    .flatMap(opt -> opt.map(Stream::of).orElseGet(Stream::empty))
    .collect(Collectors.toList());

方法4:自定义收集器(更高效)

List<Order> resultObjects = orders.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.groupingBy(
            Order::getCustomerId,
            Collectors.maxBy(Comparator.comparing(Order::getOrderDate))
        ),
        map -> map.values().stream()
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.toList())
    ));

完整工作示例

List<Order> orders = Arrays.asList(
    new Order("C1", LocalDate.of(2023, 1, 10), 100.0),
    new Order("C1", LocalDate.of(2023, 2, 15), 150.0),
    new Order("C2", LocalDate.of(2023, 1, 5), 200.0),
    new Order("C2", LocalDate.of(2023, 3, 20), 250.0),
    new Order("C3", LocalDate.of(2023, 2, 1), 300.0)
);

// 找出每个客户最近的订单并收集到List
List<Order> latestOrders = orders.stream()
    .collect(Collectors.groupingBy(
        Order::getCustomerId,
        Collectors.maxBy(Comparator.comparing(Order::getOrderDate))
    ))
    .values().stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

// 打印结果
latestOrders.forEach(order -> System.out.println(
    "客户 " + order.getCustomerId() + 
    " 最近的订单日期: " + order.getOrderDate() + 
    " 金额: " + order.getAmount()
));

输出结果示例

客户 C1 最近的订单日期: 2023-02-15 金额: 150.0
客户 C2 最近的订单日期: 2023-03-20 金额: 250.0
客户 C3 最近的订单日期: 2023-02-01 金额: 300.0

关键点总结

  1. groupingBy + maxBy 会产生 Map<K, Optional<T>> 结构
  2. 需要额外处理Optional才能得到实际对象
  3. 推荐使用方法2或方法4,它们在性能和可读性上表现较好
  4. 如果确定每组都有值,可以使用orElseThrow()替代orElse(null)

相关文章:

  • ubuntu开启黑屏现象解决
  • Linux上位机开发实践(从MPP平台到产品)
  • AI大模型从0到1记录学习 day10
  • SvelteKit 最新中文文档教程(16)—— Service workers
  • 【Unity】记录TMPro使用过程踩的一些坑
  • SpringBoot整合LogStash,LogStash采集服务器日志
  • vue 4 组件通信
  • C语言字符串处理相关函数详解
  • T11 TensorFlow入门实战——优化器对比实验
  • NE 综合实验3:基于 IP 配置、链路聚合、VLAN 管理、路由协议及安全认证的企业网络互联与外网访问技术实现(H3C)
  • Spring Data JPA方法命名规则的完整总结,按场景分类整理
  • 解决在pycharm下载的python在cmd命令行无法识别的问题
  • 蓝桥杯最后十天冲刺day 1
  • mysql表连接方式
  • MSYS2学习笔记
  • Unity 2022.3.x部分Android设备播放视频黑屏问题
  • 华为三进制逻辑与高维量子计算的对比分析
  • 微服务面试题:配置中心
  • Docker学习--容器生命周期管理相关命令--start/stop/restart命令
  • 装饰器模式:如何用Java打扮一个对象?
  • html电影网站模板/销售成功案例分享
  • 广州建站招聘/智慧软文发稿平台
  • 南京网站开发公司排名/顾问
  • 个人网站源码下载/外贸平台
  • html建设网站/网址提交入口
  • 芜湖炎黄做的网站/鞍山seo外包