java

java-stream(一)

2022-01-04  本文已影响0人  go_2021

吾尝终日而思矣,不如须臾之所学以。

这个流是干啥的?

流可以简单理解为,把我们业务中数据过滤,分页,求和,分类汇总等一些类似于mysql中的一些聚合函数功能给封装了一下,在写类似功能的时候直接. stream.grougbying(),需要干啥就点啥就行了,写的时候比较丝滑,另外还提供了对fork/join的封装,数据量大的时候直接.stream()换成,. paraealStream() 就可以了,让CPU都忙起来,这操作我就问你,丝滑不?

这个流有啥特点?
  1. 只会执行一次(只会循环一次)。
  2. 结束操作才会执行。
  3. 不会影响原值。

只会执行一次如何理解呢?

List<Integer> integers = Arrays.asList(1, 2, 3);
long count = integers.stream().filter(x -> {
            System.out.println("a");
            return x > 1;
        }).filter(x ->
        {
            System.out.println("b");
            return x < 3;
        }).count();

会打印aaabbb? aaabb?不对的。会打印aabab。一个元素只会过一遍,被pass,就下一个元素继续。
第二个惰性加载就是要执行到结束操作才会执行,把上面的例子改一下:

List<Integer> integers = Arrays.asList(1, 2, 3);
Stream<Integer> integerStream = integers.stream().filter(x -> {
            System.out.println("a");
            return x > 1;
        }).filter(x ->
        {
            System.out.println("b");
            return x < 3;
        });

少个count()方法的调用,那么会打印什么的?是啥都不打印。因为没有执行终止操作,只有中间操作,那哪些是中间操作哪些是终止操作呢?后面会说。
第三条不会影响原值就很好理解了,不管经历流的操作,integers这个list是不会发生变化的。

流方法分类?

大致是这么分类的,中间操作不会触发执行,结束操作才会。
有无状态可以理解为处理元素是否受前后元素的影响,sorted()排序操作肯定是受前后元素影响啊,所以是划分为有状态
短路非短路就类似java中的&&&|||区别。
基于什么实现的?

因为jdk1.8的函数式接口和lambda表达式的支持。
有且仅有一个抽象方法的接口一般会有@FunctionalInterface注解函数式接口可以被隐式转换为lambda表达式,可以有多个默认方法。
lambda表达式:
(parameters)->expression
(parameters)->{statements;}
lambda又可以简化为方法引用更简洁:ClassName::methodName

optional嵌套用法
    // 第一种方式:各种if判断避免了空指针,但是if层级太深,代码冗长
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            Country country = address.getCountry();
            if (country != null) {
                String couName = country.getCountryName();
                System.out.println( "第二种方式:" + couName );
            }
        }
    }

    // 第二种方式:代码简洁,避免空指针
    String counName = Optional.ofNullable( user )
            .map( User::getAddress )
            .map( Address::getCountry )
            .map( Country::getCountryName )
            .orElse( "china" );
    System.out.println( "第三种方式:" + counName );

    // 第三种方式:代码简洁,避免空指针,武林那一步为空都会返回自定义异常
    String countryNameEx = Optional.ofNullable( user )
            .map( User::getAddress )
            .map( Address::getCountry )
            .map( Country::getCountryName )
            .orElseThrow( () -> new RuntimeException( "countryId is null" ) );
有啥需要注意的?
  1. lambda表达式中变量会隐性的添加final关键字的,所以如果你要重新赋值就会报错:
  1. 流不能重复消费还不能修改原值,要不运行就抛异常:



  2. 不能像for循环一样直接return退出方法
  3. 异常相关,增加了异常堆栈的深度,受检异常还不能委托给方法向上抛出,只能自己在lambda中处理:
integers.stream().forEach(x->{
            try {
                throw new Exception("dfd");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

感觉好用是好用,但是当我一不注意踩到坑的时候。不知道为啥,我就会想到这张图:


参考:
https://www.jianshu.com/p/3d4e76467990
https://www.cnblogs.com/xzy-/p/10915920.html
https://blog.csdn.net/Goodbye_Youth/article/details/106879287
https://www.jianshu.com/p/e81f2f2f68b8
https://www.cnblogs.com/CarpenterLee/p/6637118.html
https://blog.csdn.net/iteye_1287/article/details/82540162?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

上一篇下一篇

猜你喜欢

热点阅读