资源说明: Java 8 Stream 操作类型及 peek 示例解析
Java 8 中的 Stream 操作类型可以分为两种:中间操作和终止操作。中间操作是对数据的加工,对 Stream 中的元素进行某些操作,但是这些操作不会立马启动,需要等待终止操作才会执行。终止操作是 Stream 的启动操作,只有加上终止操作,Stream 才会真正的开始执行。
peek 是一个中间操作,主要被用在 debug 用途。例如,在使用 filter 或 map 等操作时,可以使用 peek 来输出中间结果,方便调试。但是,需要注意的是,peek 只是对 Stream 中的元素进行某些操作,但是这些操作不会改变 Stream 中的元素。
例如,下面的代码使用 peek 来输出 Stream 中的元素:
```java
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());
```
输出结果:
```
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
```
可以看到,peek 输出了 Stream 中的中间结果,方便调试。
但是,如果使用 peek 来转换 Stream 中的元素,例如:
```java
Stream.of("one", "two", "three", "four").peek(u -> u.toUpperCase()).forEach(System.out::println);
```
输出结果:
```
one
two
three
four
```
可以看到,Stream 中的元素并没有被转换成大写格式。这是因为 peek 只是对 Stream 中的元素进行某些操作,但是这些操作不会改变 Stream 中的元素。
相比之下,map 操作则可以真正的对 Stream 中的元素进行转换,例如:
```java
Stream.of("one", "two", "three", "four").map(u -> u.toUpperCase()).forEach(System.out::println);
```
输出结果:
```
ONE
TWO
THREE
FOUR
```
可以看到,map 操作真正的对 Stream 中的元素进行了转换。
另外,如果 Stream 中的元素是对象,例如:
```java
List userList = Stream.of(new User("a"), new User("b"), new User("c"))
.peek(u -> u.setName("kkk"))
.collect(Collectors.toList());
```
输出结果:
```
[PeekUsage.User(name=kkk), PeekUsage.User(name=kkk), PeekUsage.User(name=kkk)]
```
可以看到,如果是对象的话,实际的结果会被改变。这是因为 peek 操作可以改变 Stream 中的对象的状态。
为什么 peek 和 map 有这样的区别呢?这主要是因为 peek 接收一个 Consumer,而 map 接收一个 Function。Consumer 是没有返回值的,它只是对 Stream 中的元素进行某些操作,但是操作之后的数据并不返回到 Stream 中,所以 Stream 中的元素还是原来的元素。而 Function 是有返回值的,这意味着对于 Stream 的元素的所有操作都会作为新的结果返回到 Stream 中。
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。