Skip to main content
 首页 » 编程设计

Java 流peek() API

2022年07月19日215jyk

Java 8 流peek() API

本文介绍了Java 8 流peek()api,因为其通常被误解或误用。

1. 从示例开始

首先从示例开始,在控制台中打印字符串流,因为peek需要Consumer 作为参数,尝试代码如下:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck"); 
nameStream.peek(System.out::println); 

但上述代码没有输出,这是为什么?

回顾下流,其有三个部分,数据源,零个或多个中间操作,零个或多个终止操作。
数据源提供元素给流程。中间操作一个一个获取元素并处理,所有中间操作是延迟执行,直到流程开始执行才开始真正执行。终止操作意味着流生命周期结束,更重要的是终止操作启动流程开始工作。从而提升执行效率,避免中间操作做无用功,底层实现了熔断机制,只有需要才执行。

因此,上面代码因为没有终止操作,实际并没有执行,一般流都需要有终止操作启动流程执行。

2. peek()使用

首先我们修改上面的示例,改用forEach:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck"); 
nameStream.forEach(System.out::println); 

peek官方文档说明:peek方法主要用于调试,在流程某个步骤查看执行元素情况。
根据官网提示在看个示例:

Stream.of("one", "two", "three", "four") 
  .filter(e -> e.length() > 3) 
  .peek(e -> System.out.println("Filtered value: " + e)) 
  .map(String::toUpperCase) 
  .peek(e -> System.out.println("Mapped value: " + e)) 
  .collect(Collectors.toList()); 

这个示例可以观察到元素流过每个操作的值。除此之外,peek()在另一个场景中也很有用:改变一个元素的内部状态。例如我们想要在打印所有用户名之前将其转换为小写:

Stream<User> userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck")); 
userStream.peek(u -> u.setName(u.getName().toLowerCase())) 
          .forEach(System.out::println); 

当然也可以使用map,当peek更方便,因为无需替换元素。

3. 总结

本文我们从流程的生命周期角度理解peek,通过示例介绍了两个典型使用场景。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/106277596
阅读延展