Java Stream API 不存储数据、不修改源集合,其“不可变性”指操作无副作用;真正运行时不可变的是 JDK 9 的 List.of()、Set.of()、Map.of() 等工厂方法创建的集合。

Java Stream API 本身不存储数据,也不修改原始集合,它的“不可变性”体现在操作过程的无副作用和不改变源数据上——这是设计哲学,不是语法强制。真正具备不可变语义的是 JDK 9 引入的 List.of()、Set.of()、Map.of() 等工厂方法创建的集合,它们才是运行时真正不可修改的对象。
Stream 流操作天然不修改源集合
Stream 是对数据源的一次性管道式处理,所有中间操作(如 filter、map、sorted)都返回新流,终结操作(如 collect、forEach)也只读取元素,不会调用原集合的 add/remove/set 等方法。
- 哪怕你对 ArrayList 调用 stream(),filter 后再 collect 回新 List,原 ArrayList 内容始终不变
- 若源是不可变集合(如 List.of("a","b")),Stream 操作更安全——连意外修改的入口都没有
- 注意:Stream 不阻止你写有副作用的 lambda(比如在 map 里修改外部变量或调用非纯方法),但这违背 Stream 设计初衷
不可变集合是 Stream 的理想输入源
用 List.of()、Set.of() 创建的数据天然适配 Stream 流程,避免了防御性拷贝、并发修改异常(ConcurrentModificationException)等隐患。
- List.of("apple", "banana", "cherry").stream().filter(s -> s.length() > 5).toList() —— 安全、简洁、线程友好
- Set.of(1, 2, 3, 4).stream().map(x -> x * 2).collect(Collectors.toSet()) —— 输入唯一、输出可控
- Map.of("name", "Alice", "age", 30).entrySet().stream() —— 直接流化键值对,无需额外转换
Map 不可变集合的特殊限制需留意
Map.of() 最多支持 10 个键值对;超过请用 Map.ofEntries() 或 Map.copyOf(),否则编译或运行时报 IllegalArgumentException。
立即学习“Java免费学习笔记(深入)”;
- ✅ 正确:Map.of("k1", 1, "k2", 2)
- ✅ 正确:Map.ofEntries(Map.entry("k1",1), Map.entry("k2",2), ..., Map.entry("k11",11))
- ❌ 错误:Map.of("k1",1,"k2",2,...,"k11",11) —— 编译失败(参数超限)
- ⚠️ 注意:Map.copyOf(existingMap) 在 JDK 10+ 可安全转为不可变副本,即使原 Map 是可变的
不可变集合 + Stream 是防御性编程的好组合
当你暴露一个集合给外部模块(比如 API 返回值、配置项、常量数据),用不可变集合封装 + Stream 处理,能兼顾安全性与表达力。
- 例如:public static final List
SUPPORTED_FORMATS = List.of("JSON", "XML", "YAML"); - 调用方只能 Stream.filter(...).findAny(),无法误删或篡改格式列表
- 内部逻辑可放心用 .stream().anyMatch(...) 判断,无需同步或复制校验



















