【Java 8 新特性】Java Stream通过peek在调用子元素时执行方法
- 1. Stream.peek() : 是一个中间操作(`An Intermediate Operation`)
- 2.peek()示例
- 3.`peek()`并行流(`Parallel Stream`)示例
- 4.Java 9中的`peek()`和`count()`
- 参考文献
本页将介绍
Stream.peek
方法示例。
peek
方法返回由该流的元素组成的流,并对每个元素执行所提供的
Consumer
操作方法。
peek
是一个中间操作方法。
从javadoc中找到peek
方法语法。
Stream<T> peek(Consumer<? super T> action)
参数:将Consumer
作为操作方法传递。
返回:该方法返回一个新的流。
peek
方法主要用于调试,以便在元素流过管道中的某个点时查看它们。
在并行流操作中,peek
方法的操作可以在上游操作使元素可用的任何时间和线程中被调用。
peek
方法是中间方法,将在调用终端方法时执行。但是在Java9中,对于count()
这样的短路操作,peek
方法中的操作不会被这些元素调用。
1. Stream.peek() : 是一个中间操作(An Intermediate Operation)
peek
方法是中间方法,因此在调用终端方法之前它不会执行。让我们举个例子来看看。找到我们没有调用任何终端方法的peek
方法。
Stream.of(10, 20, 30).peek(e -> System.out.println(e));
不会有输出。
现在在上面的代码中使用一个终端方法,我们将得到peek
方法的输出。
Stream.of(10, 20, 30).peek(e -> System.out.println(e))
.collect(Collectors.toList());
查看输出。
10 20 30
2.peek()示例
peek
方法主要用于调试。查看例子。
示例1:我们有一个整数流。首先我们将过滤,然后调试,然后映射,然后再次调试。
Stream.of(10, 11, 12, 13)
.filter(n -> n % 2 == 0)
.peek(e -> System.out.println("Debug filtered value: " + e))
.map(n -> n * 10)
.peek(e -> System.out.println("Debug mapped value: " + e))
.collect(Collectors.toList());
输出
Debug filtered value: 10
Debug mapped value: 100
Debug filtered value: 12
Debug mapped value: 120
示例2:在这个例子中,我们有一个重复值的列表。我们将找到不同的值并使用peek
方法进行调试。
List<String> list = Arrays.asList("AA", "BB", "CC", "BB", "CC", "AA", "AA");
String output = list.stream()
.distinct()
.peek(e -> System.out.println("Debug value: " + e))
.collect(Collectors.joining(","));
System.out.println(output);
输出
Debug value: AA
Debug value: BB
Debug value: CC
AA,BB,CC
示例3:在这个例子中,我们将使用peek
方法在列表中存储数据。
PeekDemo.java
package com.concretepage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PeekDemo {
public static void main(String[] args) {
List<String> debugList = new ArrayList<>();
List<String> names = Arrays.asList("Mahesh", "Suresh", "Mahendra");
names.stream()
.filter(el -> el.startsWith("M"))
.peek(e -> debugList.add(e))
.collect(Collectors.toList());
System.out.println(debugList);
}
}
输出
[Mahesh, Mahendra]
3.peek()并行流(Parallel Stream)示例
我们知道在并行流操作中,peek
方法可以在上游操作使元素可用的任何时间和线程中被调用。因此peek
方法接收到的元素可能会因多次运行而有所不同。
查看例子
PeekDemoParallel.java
package com.concretepage;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class PeekDemoParallel {
public static void main(String[] args) {
List<Integer> sortedList = Stream.of(15, 10, 17, 11)
.parallel()
.sorted()
.peek(e -> System.out.println("Debug: " + e))
.collect(Collectors.toList());
System.out.println("---After sorting---");
System.out.println(sortedList);
}
}
输出
Debug: 15
Debug: 11
Debug: 17
Debug: 10
---After sorting---
[10, 11, 15, 17]
4.Java 9中的peek()和count()
在Java9中,对于像count()
这样的短路操作,peek
方法中的操作不会被这些元素调用。peek
方法不向流中注入元素或从流中移除元素。
在流源中,元素的数量是已知的,count
是流列表的大小,因此不需要执行管道。
查看代码
long cnt = Stream.of(10, 11, 12, 13)
.peek(e -> System.out.println("Debug: " + e))
.count();
System.out.println(cnt);
输出peek
将不执行,输出将只有4。
参考文献
【1】Java doc: Stream【2】Java Stream peek()