peek() 是 Java Stream 的调试用中间操作,接收 Consumer 打印或观察元素,不改变流内容,需终端操作触发,不可修改元素,并行流中顺序不保证,生产环境应避免使用。

stream().peek() 是 Java Stream API 中一个用于调试的中间操作,它不会改变流中元素本身,只在每个元素经过时执行你指定的操作(比如打印),然后原样传递下去。
peek() 的基本用法
它接收一个 Consumer 函数式接口,常用来输出当前处理的元素,方便确认流的中间状态是否符合预期。
- 必须配合终端操作(如 collect()、forEach()、count() 等)才会真正触发执行
- 如果只有 peek() 没有终端操作,整个 stream 不会运行,也就不会打印任何内容
- 它对流中每个元素都执行一次,适合观察过滤、映射前后的数据变化
常见调试场景示例
比如想查看 filter 和 map 过程中每一步的数据:
List<string> result = Arrays.asList("apple", "banana", "cherry")
.stream()
.peek(s -> System.out.println("原始: " + s))
.filter(s -> s.length() > 5)
.peek(s -> System.out.println("过滤后: " + s))
.map(String::toUpperCase)
.peek(s -> System.out.println("转大写后: " + s))
.collect(Collectors.toList());</string>
输出会是:
原始: apple 原始: banana 过滤后: banana 转大写后: BANANA 原始: cherry 过滤后: cherry 转大写后: CHERRY
peek() 的注意事项
- 不能修改流中元素(虽然语法上可以,但违背函数式设计原则,且可能引发不可预期行为)
- 不适用于需要“记录状态”的调试(比如统计 peek 调用了几次),因为它是无状态的中间操作
- 在并行流中,peek() 的执行顺序不保证,打印可能乱序,不适合依赖顺序的调试
- 生产环境应避免保留 peek(),尤其是含 I/O 的逻辑(如日志),会影响性能和可维护性
替代方案建议
如果需要更健壮的调试方式,可以考虑:
- 把流拆成多个变量,用普通变量 + 日志分步观察
- 使用 IDE 的断点调试,直接停在 map/filter 后查看集合内容
- 在单元测试中用 assert 验证中间结果(如用 toList() 截断流再检查)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











