
本文介绍如何使用 java stream api 将按字段分组的列表(如 `list
在实际开发中,常需将扁平数据按某字段(如 value)聚合并展开为结构化对象。例如,给定 PivotMapEgModel 列表,目标是生成 List
核心思路分为三步:
-
分组聚合:用 Collectors.groupingBy 按 getValue() 分组,并用 Collectors.mapping 提取所有 getCode() 值为 List
; -
转换条目:对分组结果的 entrySet() 流式遍历,将每个 (key, List
) 映射为 ResultSet; - 安全取值:通过辅助方法 getCode(list, index) 防止 IndexOutOfBoundsException,索引越界时返回 null。
以下是完整可运行示例:
import java.util.*;
import java.util.stream.Collectors;
@Data
@AllArgsConstructor
class ResultSet {
long value;
String code_1;
String code_2;
String code_3;
}
class PivotMapEgModel {
private final long value;
private final String code;
PivotMapEgModel(long value, String code) {
this.value = value;
this.code = code;
}
long getValue() { return value; }
String getCode() { return code; }
}
// 主逻辑
public class StreamToCustomObject {
public static void main(String[] args) {
List pivotMapList = List.of(
new PivotMapEgModel(1L, "1"),
new PivotMapEgModel(1L, "2"),
new PivotMapEgModel(1L, "3"),
new PivotMapEgModel(2L, "5")
);
List result = pivotMapList.stream()
.collect(Collectors.groupingBy(
PivotMapEgModel::getValue,
Collectors.mapping(PivotMapEgModel::getCode, Collectors.toList())
))
.entrySet()
.stream()
.map(entry -> new ResultSet(
entry.getKey(),
getCode(entry.getValue(), 0),
getCode(entry.getValue(), 1),
getCode(entry.getValue(), 2)
))
.collect(Collectors.toList());
System.out.println(result);
// 输出: [ResultSet(value=1, code_1=1, code_2=2, code_3=3),
// ResultSet(value=2, code_1=5, code_2=null, code_3=null)]
}
private static String getCode(List codes, int index) {
return index < codes.size() ? codes.get(index) : null;
}
} ✅ 关键注意事项:
立即学习“Java免费学习笔记(深入)”;
- 分组后直接操作 entrySet().stream() 是连接聚合与构造的关键桥梁;
- 避免在 map() 中硬编码 list.get(i),必须封装边界检查,否则流式处理会因单个异常而中断整个流水线;
- 若业务允许,也可用 Optional.ofNullable(...).orElse(null) 等方式增强可读性,但本例中自定义 getCode 更简洁高效;
- 此方案时间复杂度为 O(n),仅一次遍历 + 一次分组后遍历,性能优秀且语义清晰。
该模式适用于任何“分组 → 展开为固定宽表”的场景,是 Java Stream 进阶应用的典型范式。










