为了账号安全,请及时绑定邮箱和手机立即绑定

jdk10中stream流里面peek方法注意点

标签:
Java

最近在我的课程里面SpringBoot2.0不容错过的新特性 WebFlux响应式编程里面,有学员提出了以下问题,在jdk10里面代码没有执行(课程中stream流是用jdk8演示的)


代码:

public class LambdaDemo {
    public static void main(String[] args) {
       IntStream.range(1,10).peek(LambdaDemo::debug).count();
    }

    public static void debug(int i) {
        System.out.println(Thread.currentThread().getName() + " " + " debug " + i);
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


jdk10运行不会产生结果,8就没有问题

https://img1.sycdn.imooc.com//szimg/5b2a3a020001ea1116950752.jpg

https://img1.sycdn.imooc.com//szimg/5b2a3a020001270817080901.jpg


我第一个感觉是不可能,觉得是学员搞错了,理论上jdk不可能不兼容的,让学员检查代码和环境。学员检查之后说确实如此,于是我在jdk10下运行测试,确实如学员所说,peek的日志没有打印出来。


看来即使工作校验再丰富的人,也会因为想当然犯错误。于是我翻了以下jdk10的api说明,最终发现不是代码没有执行,而是jdk10下调用count方法的时候,peek方法没有执行!


jdk说明:

https://img1.sycdn.imooc.com//5b2da67900010d1d09860600.jpg

api上说了,count方法的时候,peek不会执行。所以上面代码不是没有执行,而是peek方法没有执行

public class LambdaDemo {
    public static void main(String[] args) {
        long count = IntStream.range(1,10).peek(LambdaDemo::debug).count();
        System.out.println("count=" + count);
    }

    public static void debug(int i) {
        System.out.println(Thread.currentThread().getName() + " " + " debug " + i);
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上面代码里面,可以打印出count=9,但peek日志没有打印(jdk8里面能打印)。需要说明的是,peek方法不是都不会执行,调用count不会执行,调用sum的时候就会执行!


学会技术最重要的学习技术的思想


另外说明一点,我们学习一个新技术,学会api的使用只是其次的,最重要的是学会这种技术的思想。好比你学习了vue,但还是用jquery的思维来写代码,这都是不对的!回到我们的函数式编程里面,函数式编程里面,对象在流操作(函数操作里面)里面,不应该产生任何修改(副作用side-effects),修改对象的时候应该返回新对象。


如下代码,peek中修改了对象,产生了副作用(peek只应该用于debug作用,不应该有修改操作产生副作用)

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Demo{
    public  String msg = "初始值";
}

public class LambdaDemo2 {
    public static void main(String[] args) {
        System.out.println("jdk版本:"+ManagementFactory.getRuntimeMXBean().getVmVersion());
        List<Demo> demos  = new ArrayList<Demo>();

        demos.add(new Demo());
        demos.add(new Demo());

        // 这里peek中修改了对象,产生了副作用(side-effects)
        long count = demos.stream().peek(demo -> demo.msg = "peek中修改了").count();
        System.out.println(count);

        // jdk8下下面的demo已经改变
        // jdk10下没有
        demos.stream().forEach(demo -> System.out.println(demo.msg));

    }
}

jdk8中,peek方法执行了,demo对象被修改了。输出

https://img1.sycdn.imooc.com//5b2daaa00001747802500117.jpg


而jdk10中,peek没有执行,demo对象没有修改!

https://img1.sycdn.imooc.com//5b2daaa00001b91302330119.jpg


所以,函数式编程里面,函数应该是没有副作用的,对象不应该被修改产生副作用(如果要修改应该用map方法),大家一定要用函数式的思想来写函数式的代码!




点击查看更多内容
15人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
1.1万
获赞与收藏
1074

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消