zoukankan      html  css  js  c++  java
  • 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

    本文来自于https://www.cnblogs.com/flydean/p/java-8-stream-peek.html

  • 相关阅读:
    2017(秋)软工作业: (2)硬币游戏—— 代码分析与改进
    软工作业(1)课程学习热身
    用户体验分析:以 “师路南通网站” 为例
    用户体验分析: 以 “南通大学教务管理系统微信公众号” 为例
    软件工程第二次作业:硬币游戏—— 代码分析与改进
    自我介绍
    用户体验分析---以师路南通为例
    用户体验分析---七八点照相馆
    硬币游戏—— 代码分析与改进
    About me
  • 原文地址:https://www.cnblogs.com/dyaqi/p/15242790.html
Copyright © 2011-2022 走看看