两个list合并用stream.concat最稳妥,三个及以上改用stream.of(...).flatmap(list::stream);需随机访问才collect成list,否则直接操作stream更高效。

Stream.concat 本身只支持两个 Stream 合并,强行拼多个会出错或可读性差。安全、清晰、符合习惯的做法是:两个用 Stream.concat,三个及以上改用 Stream.of(...).flatMap(List::stream)。
两个 List 合并:用 concat 最稳妥
这是 concat 的设计本意,语义明确、类型安全、不易漏写收集操作:
Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList())- 不会修改原集合,适合只读场景
- 若需去重,直接链式加
.distinct() - 注意:别忘了
.collect(...),否则返回的是 Stream,调用size()或get()会编译失败或运行时报错
三个及以上 List 合并:别硬套 concat,改用 of + flatMap
Stream.concat 是二元操作,Stream.concat(a, b, c) 编译不通过;而 Stream.concat(Stream.concat(a,b),c) 嵌套深、易出错、难维护:
- 推荐写法:
Stream.of(list1, list2, list3).flatMap(List::stream).collect(Collectors.toList()) - 扩展自然:加第四个只需在
of(...)里多传一个参数 - 底层统一处理,避免手动拼接的逻辑漏洞
- 同样支持后续操作,比如去重、过滤、映射
合并时要不要 collect 成 List?看实际需要
不是所有场景都需要一个新 List 实例。如果只是遍历、过滤或转成其他结构,跳过 collect 能省内存、减 GC 压力:
- 要随机访问(如
get(5))或多轮迭代 → 必须collect - 只做一次
forEach、filter、count或转成Set/Map→ 直接在合并后的 Stream 上操作即可 - 反例:
Stream.concat(a,b).collect(...).stream().filter(...)属于多余构造,性能白损
注意不可变集合和线程安全
addAll 看似简单,但容易在运行时抛异常:
-
Collections.unmodifiableList、Arrays.asList()返回的列表调用addAll会触发UnsupportedOperationException - 多线程环境下对同一
ArrayList并发调用addAll,没加锁会导致数据丢失 - Stream 方案天然无副作用,更适合并发或函数式风格代码











