Java 8 中用 Stream 和 Lambda 实现笛卡尔积的核心是 flatMap + map 嵌套:外层流遍历第一个集合,对每个元素用 flatMap 拉平第二个集合的映射结果,并在 map 中构造数组、List 或 DTO;支持任意类型、多集合及自定义对象,需注意空集合、基本类型流转换和内存溢出风险。

用 Java 8 的 Stream 和 Lambda 实现两个集合的笛卡尔积,核心在于 flatMap + map 的嵌套组合:外层流遍历第一个集合,对每个元素,内层流映射第二个集合的所有元素,生成成对结果。
基础写法:两个 List 的简单组合
适用于 List、List 等任意引用类型集合:
- 先将第一个集合转为 stream
- 对每个元素
a,用flatMap拉平第二个集合的 stream 映射结果 - 在
map中构造组合对象(如数组、List 或自定义 DTO)
示例代码:
List<string> colors = Arrays.asList("红", "蓝");
List<string> sizes = Arrays.asList("S", "M", "L");
List<string> result = colors.stream()
.flatMap(color -> sizes.stream()
.map(size -> new String[]{color, size}))
.collect(Collectors.toList());
// 结果:[["红","S"], ["红","M"], ["红","L"], ["蓝","S"], ["蓝","M"], ["蓝","L"]]
</string></string></string>
封装为通用方法:支持任意数量集合
当需要处理三个或更多集合(如颜色、尺寸、产地),可把它们放入一个 List,再用循环 + 累积流实现:>
- 初始化结果集为第一个集合
- 逐个与后续集合做笛卡尔积:用
stream().flatMap(...)替换当前结果 - 每次
map中拼接字符串或构建新对象
关键逻辑片段:
public static <t> List<string> descartes(List<list>> lists) {
List<string> result = new ArrayList();
for (List<t> list : lists) {
if (result.isEmpty()) {
result = list.stream().map(Object::toString).collect(Collectors.toList());
} else {
result = result.stream()
.flatMap(r -> list.stream().map(item -> r + " " + item))
.collect(Collectors.toList());
}
}
return result;
}
</t></string></list></string></t>
转为自定义对象:比如生成 SKU 组合 DTO
实际业务中往往不只要字符串拼接,而是要构造带字段的对象。例如两个 ID 列表生成 TagsAttributeDto:
- 定义 DTO 类,含
tagsId和attributeId字段 - 在
map中直接 new 实例并赋值 - 确保构造过程无副作用,符合函数式风格
示例:
public static List<tagsattributedto> descartes(List<long> tagsIds, List<long> attributesIds) {
return tagsIds.stream()
.flatMap(tagId -> attributesIds.stream()
.map(attrId -> new TagsAttributeDto(tagId, attrId)))
.collect(Collectors.toList());
}
</long></long></tagsattributedto>
注意事项与避坑点
有些场景容易出错,需特别注意:
- 不能直接对
int[]调用Arrays.stream()后 flatMap —— 它返回的是IntStream,需用mapToObj转回引用流 - 空集合参与运算时,结果为空;若需保底(如默认值),需提前判空处理
- 组合结果量呈乘积级增长(如 10×10×10=1000),大数据量时避免内存溢出,必要时改用分页或流式消费
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











