我在 Java 8 Stream API中的 map 和flatMap 中讲述了Java8 Stream API中 map
操做和 flatMap
操做的区别。而后有小伙伴告诉我 peek
操做 也能实现元素的处理。可是你知道 map
和 peek
的区别吗? map
咱们在开头文章已经讲过了,你能够去详细了解一下它,本文将重点讲解一下 peek
操做。html
peek
操做接收的是一个 Consumer<T>
函数。顾名思义 peek 操做会按照 Consumer<T>
函数提供的逻辑去消费流中的每个元素,同时有可能改变元素内部的一些属性。
这里咱们要提一下这个 Consumer<T>
以理解 什么是消费。java
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
的方式为两种:segmentfault
setter
。System.out.println(T)
Stream<String> stream = Stream.of("hello", "felord.cn"); stream.peek(System.out::println);
若是你测试了上面给出的代码你会发现,压根不会按照逻辑跑。这是为啥子呢? 这是由于流的生命周期有三个阶段:api
foreach
之类的)和 概括 (collect
)两类。还有重要的一点就是终端操做启动了流在管道中的流动。因此应该改为下面:函数
Stream<String> stream = Stream.of("hello", "felord.cn"); List<String> strs= stream.peek(System.out::println).collect(Collectors.toLIst());
好比下图,咱们给圆球加了一个框:测试
peek
操做 通常用于不想改变流中元素自己的类型或者只想操做元素的内部状态时;而 map
则用于改变流中元素自己类型,即从元素中派生出另外一种类型的操做。这是他们之间的最大区别。
那么 peek 实际中咱们会用于哪些场景呢?好比对 Stream<T>
中的 T
的某些属性进行批处理的时候用 peek
操做就比较合适。 若是咱们要从 Stream<T>
中获取 T
的某个属性的集合时用 map
也就最好不过了。ui
咱们今天了解 Stream
的 peek
操做,同时也回顾了 Stream
的生命周期。也顺带对 Consumer<T>
函数进行了讲解。并且 和 map
相互作了比较,对各自的使用场景又作了说明。相信看过本文后你对它们会有更深的理解。spa
关注公众号:Felordcn 获取更多资讯
code