flatmap将“流的流”降维为单层流,对每个元素生成子流后自动展平;不同于map保留嵌套,它适用于数组/集合嵌套结构的扁平化处理。

用 Stream.flatMap() 把多个零散数组“压平”成一个流,核心在于:每个数组先转成流,再用 flatMap 合并所有子流。它不是简单拼接,而是把“流的流”降维成“单层流”,天然适合处理嵌套结构。
理解 flatMap 的作用机制
flatMap 接收一个函数,该函数对每个元素返回一个 Stream;然后自动把所有返回的子流“展平”(flatten)成一个新流。和 map 不同,map 会保留嵌套结构(比如变成 Stream<stream>></stream>),而 flatMap 消除一层嵌套。
- 输入:一个包含数组(或集合)的流,例如
Stream<string></string> - 中间转换:对每个数组调用
Arrays.stream(arr)得到Stream<string></string> - 输出:所有数组元素合并后的单一
Stream<string></string>
常见写法:数组数组 → 单一流
假设你有一组字符串数组:
String[][] data = {
{"a", "b"},
{"c"},
{"d", "e", "f"}
};
打平处理方式如下:
Stream<string> flattened = Arrays.stream(data)
.flatMap(Arrays::stream); // 关键:每个 String[] → Stream<string></string></string>
之后可直接链式操作,比如过滤、去重、收集:
List<string> result = Arrays.stream(data)
.flatMap(Arrays::stream)
.filter(s -> s.length() == 1)
.distinct()
.collect(Collectors.toList()); // ["a", "b", "c", "d", "e", "f"]</string>
处理其他类型数组或集合混合场景
不只是 String[],任何数组类型都适用。注意泛型擦除问题,需显式指定类型或借助方法引用:
-
int[]需用IntStream.of(arr)或先转为装箱流:Arrays.stream(intArray).boxed() - 若源头是
List<string></string>,先用list.stream()再flatMap - 混合类型(如
List<object></object>中含数组和字符串),需先filter+instanceof安全转换
避免常见陷阱
空数组或 null 元素会导致运行时异常,建议提前过滤:
Arrays.stream(data)
.filter(Objects::nonNull) // 过滤掉 null 数组
.filter(arr -> arr.length > 0) // 可选:跳过空数组
.flatMap(Arrays::stream)
另外,flatMap 是懒执行的,不会立即触发计算;只有终端操作(如 collect、forEach)才会真正遍历和展开。











