Java 8 流peek() API

Java 8 流peek() API

本文介紹了Java 8 流peek()api,因爲其通常被誤解或誤用。

1. 從示例開始

首先從示例開始,在控制檯中打印字符串流,因爲peek需要Consumer 作爲參數,嘗試代碼如下:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");
nameStream.peek(System.out::println);

但上述代碼沒有輸出,這是爲什麼?

回顧下流,其有三個部分,數據源,零個或多箇中間操作,零個或多個終止操作。
數據源提供元素給流程。中間操作一個一個獲取元素並處理,所有中間操作是延遲執行,直到流程開始執行纔開始真正執行。終止操作意味着流生命週期結束,更重要的是終止操作啓動流程開始工作。從而提升執行效率,避免中間操作做無用功,底層實現了熔斷機制,只有需要才執行。

因此,上面代碼因爲沒有終止操作,實際並沒有執行,一般流都需要有終止操作啓動流程執行。

2. peek()使用

首先我們修改上面的示例,改用forEach:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");
nameStream.forEach(System.out::println);

peek官方文檔說明:peek方法主要用於調試,在流程某個步驟查看執行元素情況。
根據官網提示在看個示例:

Stream.of("one", "two", "three", "four")
  .filter(e -> e.length() > 3)
  .peek(e -> System.out.println("Filtered value: " + e))
  .map(String::toUpperCase)
  .peek(e -> System.out.println("Mapped value: " + e))
  .collect(Collectors.toList());

這個示例可以觀察到元素流過每個操作的值。除此之外,peek()在另一個場景中也很有用:改變一個元素的內部狀態。例如我們想要在打印所有用戶名之前將其轉換爲小寫:

Stream<User> userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck"));
userStream.peek(u -> u.setName(u.getName().toLowerCase()))
          .forEach(System.out::println);

當然也可以使用map,當peek更方便,因爲無需替換元素。

3. 總結

本文我們從流程的生命週期角度理解peek,通過示例介紹了兩個典型使用場景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章