最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
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 等支持日志级别的方案