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上找到。