filter()必须放在map()前以避免空指针和冗余计算;lambda须无副作用;原始类型优先用mapToInt()但需注意类型兼容性;limit()适用于取前N个,takeWhile()易误用导致提前终止。

filter() 和 map() 的链式调用必须按顺序写
Stream 处理中,filter() 要放在 map() 前面,否则可能触发不必要的对象创建或空指针。比如对 List 先 map() 成长度再 filter(),会导致所有字符串都执行 length();而先 filter() 掉 null 或空串,能跳过后续计算。
- 常见错误现象:
NullPointerException出现在map()里,但源头是没在前面过滤掉 null 元素 - 使用场景:处理数据库查询结果、HTTP 响应体、CSV 解析后的 List,常含脏数据
- 参数差异:
filter()接Predicate,map()接Function,类型不匹配会编译失败 - 性能影响:提前
filter()可显著减少下游操作的数据量,尤其在map()含 IO 或复杂计算时
避免在 lambda 中做副作用操作
filter() 和 map() 的 lambda 必须是无状态、无副作用的。比如在 map() 里修改外部集合、写日志、更新静态计数器,会导致行为不可预测——并行流下结果错乱,调试时偶发成功、偶发失败。
- 常见错误现象:并行流下日志重复打印、集合 size 不一致、某些元素“消失”
- 使用场景:日志埋点、缓存预热、统计计数——这些该交给
peek()(仅调试)或收尾的forEach()(明确接受副作用) - 正确做法:把转换逻辑纯函数化,如
s -> s.trim().toUpperCase(),不碰任何外部变量
注意原始类型装箱与中间结果保留
用 mapToInt() 替代 map() + Integer::intValue,能避免自动装箱开销;但若后续还要转回引用类型或与其他 Stream 拼接,反而增加转换成本。
- 常见错误现象:大量
Integer对象堆积,GC 频繁,堆内存占用异常升高 - 参数差异:
mapToInt()返回IntStream,无法直接接map()(类型不兼容),得用boxed()回转,这一步有代价 - 兼容性影响:Android 低版本或老 JVM(如 Java 8u40 以前)对原始类型 Stream 优化不充分,实测未必更快
- 建议:只在明确瓶颈在装箱/拆箱、且后续全是数值计算时用
mapToInt()
短路操作别滥用,小心 skip/takeWhile 的语义陷阱
filter() 是非短路的,整个流都会遍历;但 limit()、findFirst()、anyMatch() 是短路的。想“取前 5 个非空字符串”,写成 list.stream().filter(Objects::nonNull).limit(5) 没问题;但换成 takeWhile(s -> !s.isEmpty()) 就不对——它遇到第一个空串就停,不管后面还有没有非空的。
- 常见错误现象:本想取满足条件的前 N 个,却因用了
takeWhile()或dropWhile()导致结果数量远少于预期 - 使用场景:
findAny()适合并行流找任意一个匹配项;findFirst()保证顺序,但并行时性能略低 - 容易忽略的点:
limit(n)在无限流(如Stream.iterate())中是唯一安全截断方式,否则直接 OOM
实际写的时候,最麻烦的是判断“该不该提前终止”和“要不要保留原始类型”。这两处一选错,本地跑得通,压测或换环境就出问题。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










