一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java中 Stream peek 如何做 Debug 打印调试

时间:2026-07-16 08:11:00 编辑:袖梨 来源:一聚教程网

Stream.peek()是调试流式操作最轻量的方式,它作为中间操作在每个元素经过时执行指定动作(如打印日志)却不改变数据,必须置于终止操作前才生效,常用于观察过滤、映射等中间状态。

Stream.peek() 是调试流式操作最轻量的方式,它不改变数据,只在每个元素经过时执行你指定的操作,比如打印日志。

peek 的核心作用:观察中间状态

Stream 是惰性求值的,中间操作(如 filter、map)不会立即执行,只有遇到终止操作(如 collect、forEach)才真正触发。peek 就是在这个链条中“插个眼”,让你看到某个环节的元素长什么样。

注意:peek 必须出现在终止操作之前,否则什么都不会打印。

基本用法:打印当前元素

直接传入 Lambda 表达式,用 System.out.println 输出:

立即学习“Java免费学习笔记(深入)”;

List<String> list = Arrays.asList("apple", "banana", "cherry");list.stream()    .filter(s -> s.length() > 5)    .peek(s -> System.out.println("过滤后拿到:" + s))    .map(String::toUpperCase)    .peek(s -> System.out.println("转大写后:" + s))    .collect(Collectors.toList());

输出会是:

过滤后拿到:banana转大写后:BANANA过滤后拿到:cherry转大写后:CHERRY

更实用的调试技巧

  • 打印带索引的元素:配合 AtomicInteger 或 IntStream.range,适合定位第几个元素出问题
  • 结合断点调试:在 peek 的 Lambda 里加一行 Debugger.breakpoint()(Java 14+),或直接在 IDE 中点击行号打断点(部分 IDE 支持)
  • 只对特定元素打印:加条件判断,避免刷屏,例如 .peek(s -> { if (s.contains("err")) System.out.println("可疑项:" + s); })
  • 避免副作用误用:peek 不该修改元素本身(如 s += "!"),也不该做业务逻辑(如调用 service.save()),它只是观察者

peek 和 forEach 的区别别搞混

forEach 是终止操作,执行完就结束了;peek 是中间操作,必须后面还有终止操作才能生效。下面这段代码 什么都不会打印

list.stream().peek(System.out::println); // ❌ 没有终止操作,整条流根本没运行

而这样才可以:

list.stream().peek(System.out::println).count(); // ✅ count 是终止操作

替代方案:什么时候不该用 peek

  • 需要记录完整执行路径(比如每个阶段耗时),建议用自定义工具方法包装流操作
  • 调试复杂转换逻辑,不如把流拆成变量分步执行,再用普通日志或断点
  • 生产环境禁用日志时,peek 里的 println 仍会执行 —— 应改用 SLF4J 等支持日志级别的方案

热门栏目