中间操作顺序影响性能:filter应置于map前以减少计算;sorted和distinct需慎用,避免提前加载全量数据;limit/skip配合短路终端操作可提前终止;Stream延迟执行且不可重用。

中间操作顺序直接影响执行效率和资源消耗,不是语法问题,而是性能关键点。
filter 要尽量放在 map 前面
先过滤再转换,能显著减少 map 的调用次数。比如处理十万条日志,若 90% 不满足条件,把 filter 放在 map 前,就只对 1 万条做字符串转换或对象构造,避免了九万次无意义的计算。
- 错误写法:
stream.map(...).filter(...)→ 所有元素都先经历 map - 推荐写法:
stream.filter(...).map(...)→ 只对通过 filter 的元素执行 map
sorted 和 distinct 属于有状态操作,慎放中间
它们必须缓存全部数据才能完成排序或去重,一旦出现在流水线靠前位置,就会提前把整个数据集加载进内存,失去延迟执行的优势,还可能引发 OOM。
- sorted 应尽量靠近终端操作,尤其避免放在 map 或 flatMap 后紧邻位置
- distinct 在大数据量时开销大,若上游已通过 filter 大幅缩小规模,再用 distinct 更安全
- 如果只是去重后取前 N 条,可考虑
distinct().limit(N),但注意 distinct 仍需遍历全部输入
limit 和 skip 配合短路终端操作效果突出
它们本身不触发全量计算,和 findFirst、anyMatch 这类短路操作组合,能真正“提前收工”。例如 stream.filter(...).limit(1).findFirst(),找到第一个匹配项就停止,后续元素完全不参与任何操作。
立即学习“Java免费学习笔记(深入)”;
- limit(1) 放在 filter 后,比放在 map 后更早截断数据流
- skip 通常用于分页,但要注意它必须跳过指定数量元素后才开始输出,无法短路
- 避免
sorted().limit(N)处理超大数据集——sorted 会强制加载全部数据
不要忽略延迟执行的本质
中间操作链只是组装指令,不产生任何中间集合、不访问原始数据。哪怕写了二十层 .map().filter().flatMap(),只要没调用 collect、forEach、count 等终端操作,就零耗时、零内存占用。
- 调试时断点进不去 lambda?大概率是漏写了终端操作
- 同一个 Stream 对象不能重复使用,第二次调 terminal 操作会抛 IllegalStateException
- 想复用,就重新调用
list.stream()或封装成 Supplier>


















