Java 8 Stream Api 中的 peek 操做

原文連接:segmentfault.com/a/119000002…java

1. 前言

我在Java8 Stream API 詳細使用指南 中講述了 Java 8 Stream APImap 操做和 flatMap 操做的區別。而後有小夥伴告訴我 peek 操做 也能實現元素的處理。可是你知道 mappeek 的區別嗎? map 咱們在開頭文章已經講過了,你能夠去詳細瞭解一下它,本文將重點講解一下 peek 操做。編程

2. peek

peek 操做接收的是一個 Consumer<T> 函數。顧名思義 peek 操做會按照 Consumer<T> 函數提供的邏輯去消費流中的每個元素,同時有可能改變元素內部的一些屬性。 這裏咱們要提一下這個 Consumer<T> 以理解 什麼是消費。segmentfault

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());
複製代碼

好比下圖,咱們給圓球加了一個框: ui

在這裏插入圖片描述

3. peek VS map

peek 操做 通常用於不想改變流中元素自己的類型或者只想元素的內部狀態時;而 map 則用於改變流中元素自己類型,即從元素中派生出另外一種類型的操做。這是他們之間的最大區別。 那麼 peek 實際中咱們會用於哪些場景呢?好比對 Collection<T> 中的 T 的某些屬性進行批處理的時候用 peek 操做就比較合適。 若是咱們要從 Collection<T> 中獲取 T 的某個屬性的集合時用 map 也就最好不過了。spa

4. 總結

咱們今天瞭解 Streampeek 操做,同時也回顧了 Stream 的生命週期。也順帶對 Consumer<T> 函數進行了講解。並且 和 map 相互作了比較,對各自的使用場景又作了說明。相信看過本文後你對它們會有更深的理解。code

(想自學習編程的小夥伴請搜索圈T社區,更多行業相關資訊更有行業相關免費視頻教程。徹底免費哦!)cdn

相關文章
相關標籤/搜索