Stream中的Peek操作代码
作者:自律的西瓜L
peek()是一个Intermediate操作,它接收一个Consumer类型的lambda参数(void类型),对每个元素执行操作并返回一个新的Stream,并可以继续进行流的操作。peek()方法不会影响原始流中的元素。
1.引言
如果你试图对流操作中的流水线进行调试, 了解stream流水线每个操作之前和操作之后的中间值, 该如何去做?
首先我们看一个例子, 使用forEach将流操作的结果打印出来.
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekTestOne { public static void main(String[] args) { List<Integer> list = Arrays.asList(4, 7, 9, 11, 12); list.stream() .map(x -> x + 2) .filter(x -> x % 2 != 0) .limit(2) .forEach(System.out::println); } } 输出结果如下: 9 11
可以很明显的看出, 一旦调用了forEach操作, 整个流就会恢复运行.并不能很好的帮助我们了解Stream流水线中的每个操作(如:map,filter,limit等)产生的输出.
再来看一个例子
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekTestTwo { public static void main(String[] args) { Stream<Integer> stream = Arrays.asList(4, 7, 9, 11, 12).stream(); stream.peek(System.out::println); } } 这段代码是想打印stream中的值,却没有任何输出.
2.中间操作和终止操作
中间操作是流水线中的数据进行加工的, 它是一个懒操作, 并不会马上执行, 需要等待有终止操作的时候才会执行.
终止操作是Stream的启动操作, 当有终止操作的时候, Stream才会真正的开始执行.
因此, 这里可以解释上面的peek操作是一个中间操作, 所以没有任何输出.
3.使用peek进行debug操作
peek的设计初衷就是在流的每个元素恢复运行之前的时候插入一个执行操作. 它不想forEach那样恢复整个流的运行操作. 而是在一个元素上完成操作之后, 它只会将操作顺承到流水线的下一个操作. 它能够将中间变量的值输出到日志. 有效的帮助我们了解流水线的每一步操作的输出值.如下图:
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekTestThree { public static void main(String[] args) { List<Integer> list = Arrays.asList(4, 7, 9, 11, 12); list.stream() .peek(x -> System.out.println("stream: " + x)) .map(x -> x + 2) .peek(x -> System.out.println("map: " + x)) .filter(x -> x % 2 != 0) .peek(x -> System.out.println("filter: " + x)) .limit(2) .peek(x -> System.out.println("limit: " + x)) .collect(toList()); } } 输出结果如下: stream: 4 map: 6 stream: 7 map: 9 filter: 9 limit: 9 stream: 9 map: 11 filter: 11 limit: 11 Process finished with exit code 0
4.peek和map的区别
使用peek操作流,流中的元素没有改变。
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekAndMapTestOne { public static void main(String[] args) { Arrays.asList("a","b") .stream() .peek(x -> x.toUpperCase()) .forEach(System.out::println); } } 输出: a b Process finished with exit code 0
使用map操作流,流中的元素有改变。
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekAndMapTestTwo { public static void main(String[] args) { Arrays.asList("a","b") .stream() .map(x -> x.toUpperCase()) .forEach(System.out::println); } } 输出: A B Process finished with exit code 0
可以通过上面两个例子看出,map操作是对元素进行了转换。
注意:peek对一个对象进行操作的时候,对象不变,但是可以改变对象里面的值.如下:
/** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ @Getter @Setter @AllArgsConstructor @ToString public class Person { private String id; private String name; } ---------------------------------------------------------------------------- /** * @author lyh * @version v-1.0.0 * @since 2021/5/28 */ public class PeekAndMapTestThree { public static void main(String[] args) { Arrays.asList(new Person("001","zs"),new Person("002","ls")) .stream().peek(p -> p.setId("000")).forEach(System.out::println); } } 输出: Person(id=000, name=zs) Person(id=000, name=ls) Process finished with exit code 0
peek的定义
Stream<T> peek(Consumer<? super T> action);
peek方法接收一个Consumer的入参. 了解λ表达式的应该明白 Consumer的实现类应该只有一个方法,该方法返回类型为void. 它只是对Stream中的元素进行某些操作,但是操作之后的数据并不返回到Stream中,所以Stream中的元素还是原来的元素.
map的定义
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
map方法接收一个Function作为入参. Function是有返回值的, 这就表示map对Stream中的元素的操作结果都会返回到Stream中去.
到此这篇关于Stream中的Peek操作的文章就介绍到这了,更多相关Stream Peek操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!