Java 8 Stream操作类型及peek示例解析
简介
java 8 stream作为流式操作有两种操作类型,中间操作和终止操作。这两种有什么区别呢?
我们看一个peek的例子:
Stream<String> stream = Stream.of("one", "two", "three","four");
stream.peek(System.out::println);
上面的例子中,我们的本意是打印出Stream的值,但实际上没有任何输出。
为什么呢?
中间操作和终止操作
一个java 8的stream是由三部分组成的。数据源,零个或一个或多个中间操作,一个或零个终止操作。
中间操作是对数据的加工,注意,中间操作是lazy操作,并不会立马启动,需要等待终止操作才会执行。
终止操作是stream的启动操作,只有加上终止操作,stream才会真正的开始执行。
所以,问题解决了,peek是一个中间操作,所以上面的例子没有任何输出。
peek
我们看下peek的文档说明:peek主要被用在debug用途。
我们看下debug用途的使用:
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
上面的例子我们输出了stream的中间值,方便我们的调试。
为什么只作为debug使用呢?我们再看一个例子:
Stream.of("one", "two", "three","four").peek(u -> u.toUpperCase())
.forEach(System.out::println);
上面的例子我们使用peek将element转换成为upper case。然后输出:
one
two
three
four
可以看到stream中的元素并没有被转换成大写格式。
再看一个map的对比:
Stream.of("one", "two", "three","four").map(u -> u.toUpperCase())
.forEach(System.out::println);
输出:
ONE
TWO
THREE
FOUR
可以看到map是真正的对元素进行了转换。
当然peek也有例外,假如我们Stream里面是一个对象会怎么样?
@Data @AllArgsConstructor static class User{ private String name; }
List<User> userList=Stream.of(new User("a"),new User("b"),new User("c")).peek(u->u.setName("kkk")).collect(Collectors.toList()); log.info("{}",userList);
输出结果:
10:25:59.784 [main] INFO com.flydean.PeekUsage - [PeekUsage.User(name=kkk), PeekUsage.User(name=kkk), PeekUsage.User(name=kkk)]
我们看到如果是对象的话,实际的结果会被改变。
为什么peek和map有这样的区别呢?
我们看下peek和map的定义:
Stream<T> peek(Consumer<? super T> action)
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
peek接收一个Consumer,而map接收一个Function。
Consumer是没有返回值的,它只是对Stream中的元素进行某些操作,但是操作之后的数据并不返回到Stream中,所以Stream中的元素还是原来的元素。
而Function是有返回值的,这意味着对于Stream的元素的所有操作都会作为新的结果返回到Stream中。
这就是为什么peek String不会发生变化而peek Object会发送变化的原因。
结论
我们在本文中讲解了stream的两个操作类型,并总结了peek的使用。希望大家能够掌握。
本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/stream-peek
以上就是本文的全部内容,希望对大家的学习有所帮助
您可能感兴趣的文章:
- Java8 Stream的终止操作使用示例
- 详解Java 8中Stream类型的“懒”操作
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- [Java 8] (7) 利用Stream类型的"懒"操作
- 黑马程序员--Java基础加强--17.利用反射操作泛型VI【泛型类型变量的语义】【GenericDeclaration接口】【泛型接口TypeVariable】【通过Class反射解析泛型类】
- Java8 Stream 基本操作示例
- Java实现的生成二维码和解析二维码URL操作示例
- Java8 Stream中间操作实例解析
- Java8新特性Stream短路终端操作实例解析
- 黑马程序员--Java基础加强--15.利用反射操作泛型IV【通过反射Method解析泛型方法思路】【通过Method对四种Type子接口类型进行解剖】【使用递归对任意复合泛型类型进行彻底解剖】【个人
- 详解Java 8中Stream类型的“懒”操作
- Java XML解析 - 使用SAX 示例
- 【原创】使用DOM解析XML文档示例(Java)
- java语言操作Oracle数据库中的CLOB数据类型
- 在java中对Oracle 日期类型字段的操作
- java io 对文件操作的示例
- Java操作含Clob或者NClob数据类型的存储过程实例
- Java与汇编的混合操作类库及示例
- java对XML文件的解析、节点的增加、删除操作总结
- 全面解析Java中的String数据类型