stream.concat()适用于合并两个同类型流,顺序严格且返回新流;合并多个流或类型不同时应优先用flatmap(),它支持任意数量、类型转换及链式操作,语义更灵活。

拼接两个流用 Stream.concat()
当只有两个同类型集合需要合并时,Stream.concat()是最直接的选择。它接收两个 Stream 参数,按顺序把前一个流的元素全部输出完,再输出后一个流的元素。结果流具备 SIZED 特性,便于后续操作(如 count() 或并行处理)做优化。
使用时注意:只能传两个流,不能直接处理三个及以上。如果硬要拼多个,就得嵌套调用,比如 Stream.concat(Stream.concat(a, b), c),代码可读性差,且每层 concat 都会创建中间流对象,带来额外开销。
- 适合场景:合并两个 List、两个数组流,或两个已存在的 Stream
- 不修改原集合,返回新流,符合函数式风格
- 顺序严格保证:先 a 后 b,元素位置完全可控
合并多个流优先选 flatMap()
面对三个或更多集合(比如 List<string></string> 的 list0/list1/list2/list3),flatMap 更简洁高效。典型写法是先用 Stream.of(list0, list1, list2) 构造一个“流的流”,再用 flatMap(Collection::stream) 把每一层展开成单层流。
这种方式只构建一次外层流,没有嵌套中间流,内存占用低,逻辑也清晰。它本质是“扁平化”——把多个子流摊平成一个统一的数据管道。
- 支持任意数量集合,结构统一,扩展性强
- 可配合 filter、map 等操作链式处理,例如去重、非空过滤等
- 适用于 List、Set、甚至 Map.values() 等可转 Stream 的集合类型
类型不同时 flatMap 是唯一可行方案
concat() 要求两个流元素类型必须一致。一旦遇到 List<string></string> 和 List<integer></integer> 这类异构集合,concat 会编译失败。此时只能靠 flatMap 实现语义级合并。
例如把字符串和数字组合成新字符串:list1.stream().flatMap(s -> list2.stream().map(i -> s + i)),这里 flatMap 承担了“对每个 s 生成一批新元素”的职责,不再是简单拼接,而是映射+展平的组合操作。
- concat 是物理连接,flatMap 是逻辑重组
- flatMap 的 mapper 函数返回 Stream,天然支持类型转换与衍生计算
- 即使类型相同,若需在合并过程中插入转换逻辑(如格式化、校验),flatMap 也更自然
性能与语义差异要分清
不要只看“都能把元素合在一起”,concat 和 flatMap 的底层行为完全不同。concat 是惰性串联,不触发任何中间计算;flatMap 则会对每个输入元素执行 mapper 函数,并可能触发多次 stream 构建——但现代 JVM 对短生命周期流做了大量优化,实际开销可控。
真正影响选择的是语义需求:是否要保持原始流的边界?是否要逐元素生成新流?是否涉及类型转换?明确这些,就能避开“为拼而拼”的陷阱。
- 要保留流的独立性(比如分别统计各源长度),用 concat 更合适
- 要统一处理所有元素(比如全量去重、全局排序),flatMap 更贴近意图
- 流来自不同来源(数据库分页结果、API 多次调用响应),flatMap 更易封装复用
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











