Java8中流API Peek()

1.介绍

Java Stream API 向我们介绍了处理数据的强大替代方案。

在这个文章中将重点介绍 peek(),这是一种经常被误解的方法。

2.快速开始

有一个名字流,想把它们打印到控制台。

由于 peek() 期望 Consumer 作为其唯一参数,它看起来很合适,所以试一试:

   @Test
    public void  test1(){
    
    
        Stream<String> nameStream = Stream.of("张三", "李四", "王五");
        nameStream.peek(System.out::println);
    }

但是,上面的代码片段不产生任何输出。 要了解原因,需要回顾一下流生命周期的各个方面。

3.中间与终端操作

回想一下,流由三部分组成:数据源、零个或多个中间操作以及零个或一个终端操作。

源向管道提供元素。

中间操作一一获取元素并对其进行处理。 所有中间操作都是惰性的,因此,在管道开始工作之前,任何操作都不会产生任何影响。

终端操作意味着流生命周期的结束。 对于我们的场景最重要的是,它们启动了管道中的工作。

4.peek() 用法

peek() 在我们的第一个示例中不起作用的原因是它是一个中间操作,没有对管道应用终端操作。 或者,可以使用具有相同参数的 forEach() 来获得所需的行为:

   @Test
    public void  test1(){
    
    
        Stream<String> nameStream = Stream.of("张三", "李四", "王五");
        nameStream.peek(System.out::println);
    }

peek() 的 Javadoc 页面说:“这个方法的存在主要是为了支持调试,如果希望在元素流过管道中的某个点时看到它们的值”。

例如:

   @Test
    public void test3(){
    
    
        List<String> collect = Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("过滤值: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("映射值: " + e))
                .collect(Collectors.toList());
        System.out.println(collect);
    }

输出

过滤值: three
映射值: THREE
过滤值: four
映射值: FOUR
[THREE, FOUR]

它演示了如何观察通过每个操作的元素。

最重要的是, peek() 在另一种情况下很有用:想要改变元素的内部状态时。 例如,假设想在打印之前将所有用户名转换为小写

@Data
@AllArgsConstructor
public class UserPeek {
    
    

    private String name;
}
@Test
    public void test4(){
    
    
        Stream<UserPeek> userStream = Stream.of(new UserPeek("Alice"), new UserPeek("Bob"), new UserPeek("Chuck"));
        userStream.peek(u -> u.setName(u.getName().toLowerCase()))
                .forEach(System.out::println);
    }

输出

UserPeek(name=alice)
UserPeek(name=bob)
UserPeek(name=chuck)

或者,可以使用 map(),但 peek() 更方便,因为不想替换元素。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/niugang0920/article/details/120427828