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