我在 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