美文网首页
Java 8 Stream Api 中的 peek 操作

Java 8 Stream Api 中的 peek 操作

作者: DaphX | 来源:发表于2022-08-09 10:46 被阅读0次

    1. 前言

    你知道 mappeek 的区别吗?本文将重点讲解一下 peek 操作。

    2. peek

    peek 操作接收的是一个 Consumer<T> 函数。顾名思义 peek 操作会按照 Consumer<T> 函数提供的逻辑去消费流中的每一个元素,同时有可能改变元素内部的一些属性。这里我们要提一下这个 Consumer<T> 以理解 什么是消费。

    2.1 什么是消费 (Consumer)

    package java.util.function;
    
    import java.util.Objects;
    
    @FunctionalInterface
    public interface Consumer<T> {
    
        void accept(T t);
    
         // 嵌套accept , 顺序为先执行 accept 后执行参数里的 after.accpet
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
     }
    

    Consumer<T> 是一个函数接口。一个抽象方法 void accept(T t) 意为接受一个 T 类型的参数并将其消费掉。其实消费给我的感觉就是 “用掉” ,自然返回的就是 void 。通常“用掉” T 的方式为两种:

    • T 本身的 void 方法 比较典型的就是 setter
    • 把 T 交给其它接口(类)的 void 方法进行处理 比如我们经常用的打印一个对象 System.out.println(T)

    2.2 peek 操作演示

     Stream<String> stream = Stream.of("hello", "felord.cn");
     stream.peek(System.out::println);
    

    如果你测试了上面给出的代码你会发现,压根不会按照逻辑跑。这是为啥子呢?这是因为流的生命周期有三个阶段:

    • 起始生成阶段。
    • 中间操作:会逐一获取元素并进行处理。可有可无。所有中间操作都是惰性的,因此,流在管道中流动之前,任何操作都不会产生任何影响。
    • 终端操作:通常分为 最终的消费foreach 之类的)和 归纳collect)两类。还有重要的一点就是终端操作启动了流在管道中的流动。

    所以应该改成下面:

     Stream<String> stream = Stream.of("hello", "felord.cn");
     List<String> strs= stream.peek(System.out::println).collect(Collectors.toLIst());
    

    3. peek VS map

    peek 操作 一般用于不想改变流中元素本身的类型或者只想元素的内部状态时;而 map 则用于改变流中元素本身类型,即从元素中派生出另一种类型的操作。这是他们之间的最大区别。那么 peek 实际中我们会用于哪些场景呢?比如对 Collection<T> 中的 T 的某些属性进行批处理的时候用 peek 操作就比较合适。如果我们要从 Collection<T> 中获取 T 的某个属性的集合时用 map 也就最好不过了。

    相关文章

      网友评论

          本文标题:Java 8 Stream Api 中的 peek 操作

          本文链接:https://www.haomeiwen.com/subject/pvaowrtx.html