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> 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+对象拷贝更简洁(当只需部分字段修改时)

相关推荐
二月夜4 小时前
剖析Java正则表达式回溯问题
java·正则表达式
xuhaoyu_cpp_java5 小时前
项目学习(三)分页查询
java·经验分享·笔记·学习
程序员二叉5 小时前
【Java】集合面试全套精讲|HashMap/ArrayList高频考点完整版
java·面试·哈希算法
cfm_29145 小时前
JVM GC垃圾回收初步了解
java·开发语言·jvm
心之伊始6 小时前
LangChain4j RAG 实战:Java 后端如何把本地文档接入 Embedding 检索链路
java·架构·源码分析·csdn
许彰午6 小时前
17_synchronized关键字深度解析
java·开发语言
Xzh04237 小时前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
艾利克斯冰8 小时前
Java 设计模式-行为型模式(更新中)
java·开发语言·设计模式
倒霉蛋小马8 小时前
Java新特性:record关键字
java·开发语言
折哥的程序人生 · 物流技术专研9 小时前
《Java 100 天进阶之路》第95篇:消息队列基础(RocketMQ/Kafka)(2026版)
java·面试·kafka·rocketmq·java-rocketmq·求职招聘