优先选stream.concat()拼接两个流,因其类型安全、返回sized流;多个流则用flatmap()展平stream.of()构造的流集合,兼顾灵活性与内存效率,但结果流无sized特性。

Java Stream API 提供了两种主流方式实现数据流拼接与合并:一个是专为两个流设计的 Stream.concat(),另一个是更灵活、支持任意数量流的 flatMap() 方案。选哪种,取决于你手头有多少个流、是否关注性能、以及是否需要流的大小信息(SIZED)。
拼接两个流:用 Stream.concat()
这是最直观的方式,适合明确只有两个同类型流要合并的场景。
- 必须保证两个流元素类型一致,否则编译不通过
- 调用后返回新流,原流不受影响,但流只能消费一次——如果其中一个流已被 forEach 或 collect 消费过,再传入 concat 就会抛 IllegalStateException
- 返回流具有 SIZED 特性,利于后续优化(比如并行流预估分片大小)
- 示例写法:Stream.concat(list1.stream(), list2.stream())
合并多个流:优先用 flatMap()
当有 3 个、5 个甚至动态数量的流时,flatMap 是更干净、高效的选择。
- 核心思路:先用 Stream.of(stream1, stream2, stream3...) 构造一个“流的流”,再用 flatMap(Function.identity()) 展平
- 不会产生嵌套调用或中间临时流,内存开销小
- 缺点是结果流不再标记为 SIZED,某些优化策略(如提前终止判断)可能受限
- 天然兼容 null 安全处理,比如配合 Optional.stream() 过滤掉空流
实际使用中要注意的坑
很多问题不是方法不对,而是用法不当导致运行时报错或逻辑异常:
- 流已关闭不能复用:像 s1.forEach(...); Stream.concat(s1, s2) 会失败,应从原始集合重新获取流
- 来源差异大时不推荐 concat:比如一个流来自本地文件(快),另一个来自远程 API(慢且可能失败),concat 会顺序阻塞等待第二个流初始化
- 去重别直接 .distinct() 在 concat 后:若两流各自含大量重复,先分别 distinct 再合并,效率更高
- 需排序时注意时机:合并后再 sorted() 是全局排序;若各流本身有序,可用自定义归并逻辑提升性能
其他补充方案
非必须但值得了解:
- reduce + concat:适合流数量固定且较少,用 reduce 累积调用 concat,可读性略差但语义明确
- 第三方库:如 StreamEx 提供 StreamEx.concat() 支持 varargs;Jooλ 的 Seq.concat() 更函数式
- 反应式替代:高并发/异步场景下,Project Reactor 的 Flux.merge() 或 Flux.concat() 更合适
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











