Java 8 Stream如何实现List按复合键分组转Map<key, List<Object>>
Java 8 Stream实现状态流转数据分组方案
前置准备:自定义实体类
不要直接使用原生Object存储数据,先定义明确的实体类避免类型转换异常:
- 原始状态流转实体,对应输入的单条全量数据
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class StatusTransition { private String fromStatusDesc; private Integer fromId; private String toStatusDesc; private Integer toId; }
- 分组后目标状态实体(可选,若不需要精简字段可直接复用上述实体类)
@Data @NoArgsConstructor @AllArgsConstructor public class TargetStatus { private String toStatusDesc; private Integer toId; }
如果项目没有引入Lombok,手动编写getter/setter、构造方法即可。
核心分组实现
使用Collectors.groupingBy完成分组,以from_status_desc和from_id的拼接值作为分组键,同组下的目标状态集合作为value。
写法1:精简值对象(推荐,无冗余字段)
// 假设sourceList是你的原始输入数据集,类型为List<StatusTransition> Map<String, List<TargetStatus>> result = sourceList.stream() .collect(Collectors.groupingBy( // 生成分组键,使用业务场景下不会出现的特殊分隔符拼接,避免键冲突 item -> item.getFromStatusDesc() + "||" + item.getFromId(), Collectors.mapping( // 映射为仅保留目标状态字段的对象 item -> new TargetStatus(item.getToStatusDesc(), item.getToId()), Collectors.toList() ) ));
写法2:复用原始实体(代码更简洁)
如果不需要精简值的字段,直接用原始实体类接收分组结果即可,同组内所有对象的fromStatusDesc、fromId字段完全一致,渲染表格时同组首行展示起始字段、后续行对应位置留空,就能得到你期望的合并单元格展示效果:
Map<String, List<StatusTransition>> result = sourceList.stream() .collect(Collectors.groupingBy( item -> item.getFromStatusDesc() + "||" + item.getFromId() ));
结果说明
用提供的测试数据集运行代码,最终返回的Map包含2个分组:
- 键为
Complete||5的分组对应长度为5的列表,依次包含Consumed(8)、Inventory(9)、Broke-Inv(10)、Hold(11)、Broke(12) - 键为
Consumed||8的分组对应长度为5的列表,依次包含Complete(5)、Inventory(9)、Broke-Inv(10)、Hold(11)、Broke-pmd(12)
注意:如果业务中
from_status_desc字段可能包含你选用的分隔符,请更换为不会出现的特殊字符;若不想用字符串作为键,可自定义键类重写equals()和hashCode()方法,以两个起始字段作为相等判断依据即可。
内容的提问来源于stack exchange,提问作者Abhilash
相关产品推荐
相关产品推荐

