Java 8 Streams peek() API

1.簡介

Java Stream API向我們介紹了處理數據的強大替代方案。

在這個簡短的教程中,我們將專注於peek() ,這是一種經常被誤解的方法。

2.快速示例

讓我們弄髒雙手,嘗試使用peek() 。我們有一個名字流,我們想將它們打印到控制台。

由於peek()期望將Consumer<T>作為其唯一參數,因此這似乎很合適,因此讓我們嘗試一下:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");

 nameStream.peek(System.out::println);

但是,上面的代碼段不產生任何輸出。為了理解原因,讓我們快速回顧一下流生命週期的各個方面。

3.中級與終端操作

回想一下,流具有三個部分:數據源,零個或多個中間操作以及零個或一個終端操作。

源向管道提供元素。

中間操作會逐一獲取元素並進行處理。所有中間操作都是惰性的,因此,在管道開始工作之前,所有操作都不會起作用。

終端操作意味著流生命週期的結束。對於我們的方案而言,最重要的是,它們在管道中啟動工作

4. peek()用法

peek()在我們的第一個示例中不起作用的原因是它是一個intermediate操作,並且我們沒有對管道應用terminal操作。或者,我們可以將forEach()與相同的參數一起使用以獲得所需的行為:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");

 nameStream.forEach(System.out::println);

peek()Javadoc頁面上說:“該方法主要用於支持調試,當元素流過管道中的某個點時,您希望在其中看到它們。”

讓我們考慮來自同一Javadoc頁面的以下代碼段:

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()在另一種情況下很有用:當我們想要更改element的內部狀態時。例如,假設我們要在打印所有用戶名之前將其轉換為小寫:

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()更為方便,因為我們不想替換元素。

5.結論

在這個簡短的教程中,我們看到了流生命週期的摘要,以了解peek()工作原理。當使用peek()是最簡單的選項時,我們還看到了兩個日常用例。

和往常一樣,這些示例可以在GitHub上找到