Stream API 不强制纯度,但要求开发者遵守无副作用原则:中间操作须无状态且不修改外部变量或数据源,副作用应限于终端操作;并行流更需确保线程安全与函数纯度。

Stream API 本身不强制保证纯粹性,而是通过设计约束和使用规范来支持函数式纯度——关键在于开发者是否遵守无副作用、无外部状态修改的原则。
避免在中间操作中修改外部变量
filter、map、sorted 等中间操作应只依赖输入参数,不读写类字段、静态变量或传入的可变对象。例如,不要在 map 中往外部 List 添加元素,也不要在 filter 中修改当前对象的属性。
- ❌ 错误示范:
list.stream().map(s -> { cache.add(s); return s.toUpperCase(); }) - ✅ 正确做法:所有转换逻辑仅作用于当前元素,结果通过流传递,副作用留到终端操作(如 forEach)中集中处理(且需谨慎)
确保操作无状态且不干扰数据源
所谓“无状态”,是指每个元素的处理不依赖于其他元素的处理结果或外部计数器;“不干扰”指不能在流遍历过程中修改原始集合(如 add/remove),否则可能触发 ConcurrentModificationException 或产生不可预测行为。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用不可变集合(如 List.copyOf)或复制后的副本作为流源更安全
- 排序、去重等有状态操作(如 sorted、distinct)由 Stream 内部管理状态,无需也不应由用户维护
终端操作是副作用的合理出口(但需克制)
forEach、peek(调试用)、collect 等终止操作才是执行 I/O、日志、缓存更新等副作用的合适位置。即便如此,也建议优先使用 collect 汇聚成新结构,而非直接修改外部状态。
- 推荐:
stream.collect(Collectors.toList())→ 返回新列表,原集合不变 - 慎用:
stream.forEach(item -> db.save(item))—— 若需批量写入,应结合 try-with-resources 和事务控制
并行流下纯度更重要
parallelStream() 会将任务分发到多个线程,一旦操作含共享可变状态(如 static 计数器、未同步的 Map),极易引发竞态条件。此时函数纯度不是风格选择,而是正确性前提。
- 并行时务必使用线程安全的收集器(如 Collectors.toConcurrentMap)
- 避免在 lambda 中使用 SimpleDateFormat 等非线程安全对象
- 原始类型流(IntStream)天然规避装箱副作用,更适合数值密集型纯计算

















