Java中Stream使用示例-对实体List分组且保留原数据顺序并对分组后的每组内的数据进行部分业务逻辑修改操作

场景

Java8新特性-Stream对集合进行操作的常用API:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/126070657

针对Stream的一个常用的业务场景:

对实体List分组且保留原数据顺序并对分组后的每组内的数据进行部分业务逻辑修改操作

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

先看代码实现:

复制代码
        Map<String, List<WarehouseTankInfoDTO>> dataMap = dataList.stream()
                .collect(Collectors.groupingBy(
                        WarehouseTankInfoDTO::getRelateCompanyName,
                        LinkedHashMap::new, // 保持插入顺序
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    // 对每组List<WarehouseTankInfoDTO>进行逻辑处理
                                    return list.stream()
                                            .peek(dto -> {
                                                // 示例:修改DTO的某个字段
                                                if (null != dto.getStoreName()&& null!=dto.getRelateCompanyName()&& !dto.getStoreName().equals(dto.getRelateCompanyName()) ) {
                                                    dto.setStoreName(dto.getRelateCompanyName());
                                                }
                                            })
                                            .collect(Collectors.toList());
                                }
                        )
                ));

代码详细讲解:

  1. 基础结构

    Map<String, List<WarehouseTankInfoDTO>> dataMap = dataList.stream()
    .collect(Collectors.groupingBy(...));

核心逻辑:按公司名称分组并保持原始顺序

2、分组逻辑实现

复制代码
groupingBy(
    WarehouseTankInfoDTO::getRelateCompanyName, // 分组Key提取器
    LinkedHashMap::new, // Map实现类选择
    Collectors.collectingAndThen(...)  // 下游收集器
)

LinkedHashMap::new

保证分组后的Map键顺序与数据原始出现顺序一致(普通HashMap不保证顺序)

典型应用场景:需要按特定顺序展示分组结果的报表生成

3、分组后处理

复制代码
Collectors.collectingAndThen(
    Collectors.toList(),
    list -> {
        return list.stream()
            .peek(dto -> {
                // 字段修正逻辑
                if (null != dto.getStoreName()  &&
                    null != dto.getRelateCompanyName()  &&
                    !dto.getStoreName().equals(dto.getRelateCompanyName()))  {
                    dto.setStoreName(dto.getRelateCompanyName());
                }
            })
            .collect(Collectors.toList());
    }
)

双阶段处理:

先执行常规toList()收集

然后对每个分组List进行流式处理

字段修正逻辑:

当storeName与relateCompanyName不同且非空时

用relateCompanyName覆盖storeName

业务意图:统一相同公司下的仓库名称标准

4、注意这里的peek的用法

方法定义

Stream<T> peek(Consumer<? super T> action)

类型:中间操作(Intermediate Operation)

参数:接收一个Consumer函数式接口

返回值:返回新的Stream(支持链式调用)

典型用途

调试观察:查看流处理中间状态

副作用操作:修改元素内部状态(如示例中的DTO字段修改)

日志记录:在流水线中插入日志点

选择peek()而非map()的原因是:

无返回值需求:只需要修改对象状态,不需要转换对象类型

保持流结构:不改变流中元素引用,仅修改元素内部状态

操作简洁性:比map+对象拷贝更简洁(当只需部分字段修改时)

相关推荐
SimonKing3 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean3 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven974 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55114 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河14 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
桦说编程17 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅18 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者19 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺19 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端