Java Stream是一次性惰性计算管道,不触发终端操作则中间操作不执行,不可重用,重复使用抛IllegalStateException;并行流需谨慎,小数据量反而更慢,且严禁有副作用操作。
Java 的 Stream 不是数据容器,也不替代集合;它是一次性、不可重用的计算管道——用完即弃,重复使用会抛 IllegalStateException。
写完 filter、map 这些中间操作,什么都不会发生。只有调用 collect()、forEach()、count() 等终端操作时,整个链才真正运行。
list.stream().filter(x -> x > 0).map(String::valueOf) 却没接终端操作,结果无任何输出、无异常、也无实际计算map 或 filter 中临时加 peek(System.out::println),能确认是否被触发filter 可能被 JVM 内联),但过度嵌套仍可能拖慢可读性并行流底层用的是 ForkJoinPool.commonPool(),默认线程数 = CPU 核心数 − 1。小数据量或操作本身很轻(比如 x + 1),并行反而因分片、合并、线程调度而更慢。
forEach 中修改外部变量或共享状态,例如:int[] count = {
0}; stream.parallelStream().forEach(x -> count[0]++); // 结果不确定mapToInt + sum()、collect(Collectors.groupingByConcurrent()) 等无状态聚合方式Stream 是消费型资源。一旦调用过 collect() 或 count(),再调用任何操作都会立即抛出 IllegalStateException: stream has already been operated upon or closed。
立即学习“Java免费学习笔记(深入)”;
Streams = list.stream().map(String::toUpperCase); s.count(); s.collect(Collectors.toList()); // 这里报错
list.stream().filter(...).collect(...)
stream.toCollection() 或 stream.source() 这类方法——Stream 设计上就拒绝暴露源头最常被忽略的一点:Stream 操作的「无状态」要求不是建议,而是契约。哪怕一个 map 里偷偷改了某个 static 计数器,就可能在并行时引发不可预测行为——这不是 bug,是违反模型前提的误用。