• Stream流reduce方法


    在这里插入图片描述

    reduce有三个重载方法。


    Ⅰ,一个参数使用

    在这里插入图片描述

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 2).limit(5);//1,3,5,7,9
    System.out.println(iterate.reduce((a,b)->{
        	System.out.println("a: "+a);
        	System.out.println("b: "+b);
        	return a+b;
    }).get());//25
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    第一次计算使用前两个参数,后面以上一次计算的返回值作为第一个参数,流中取下一个值作为第二个参数

    Ⅱ,两个参数使用(带初始值)

    在这里插入图片描述

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 2).limit(5);//1,3,5,7,9
    
    System.out.println(iterate.reduce(10,(a,b)->{//这里的a和b都是Integer类型
                System.out.println("a: "+a);//a的值是上一次计算的返回值或者初始值
                System.out.println("b: "+b);//b的值是流中的值
                return a+b;//返回Integer类型,一定是Integer类型,与参数identity类型保持一致
    }));//35
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    Ⅲ,三个参数使用(带初始值,并行计算,改变返回值类型)

    在这里插入图片描述
    说明下,第三个参数combiner翻译叫做“组合器”,第二个参数accumulator翻译为“累加器”,组合器只在并行流中起作用,否则不执行组合器的方法,可以使用parallel()方法将普通流转换为并行流,在普通流中调用三参数的reduce方法只起到改变返回值类型的作用。

    所谓组合器就是把各个线程中得到的计算结果进行结合。


    后两个参数他们的类型分别为BinaryOperator和BiFunction,而他们的关系如下:

    interface BinaryOperator<T> extends BiFunction<T,T,T>
    
    • 1

    所以BinaryOperator就是一种BiFunction,这两个都是函数式接口,但是他们两个的不同之处在于泛型类型,BiFunction涉及到三种类型,而BinaryOperator仅一种;

    @FunctionalInterface
    public interface BiFunction<T, U, R> {
        R apply(T t, U u);//两个不同类型的参数返回另一个类型的值
    }
    
    • 1
    • 2
    • 3
    • 4

    因为BinaryOperator继承了BiFunction,除去各自提供的一些默认实现方法,我就可以把BinaryOperator看成如下定义:

    //ps:这是我自己理解的,不是官方的代码
    @FunctionalInterface
    public interface BinaryOperator<T> {
        T apply(T t, T u);//两个同类型的参数返回同类型的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    回到reduce方法
    在这里插入图片描述
    这里就两种类型,U和T,T是流中的类型;U表示你想要得到不同于流中类型,那就传一个不同于T类型的初始变量
    假如流中为Integer类型,想要一个String类型返回值可以这样

    reduce(string,(string,int)->string,(string,string)->string);
    
    • 1

    1,演示非并行流返回值类型为流中类型

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5
            System.out.println(iterate.reduce(0,(a,b)->{
                System.out.println(Thread.currentThread().getName()+"a: "+a);
                System.out.println(Thread.currentThread().getName()+"b: "+b);
                return a+b;
            },(c,d)->{
                System.out.println(Thread.currentThread().getName()+"c: "+c);
                System.out.println(Thread.currentThread().getName()+"d: "+d);
                return c+d;
            }));//15
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    可以看到打印并没有涉及到多线程并行(没有打印mainc或maind)。
    2,演示非并行流返回类型不是流中类型

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5
            System.out.println(iterate.reduce("",(a,b)->{
                System.out.println(a.getClass()+"   "+Thread.currentThread().getName()+"a: "+a);
                System.out.println(b.getClass()+"  "+Thread.currentThread().getName()+"b: "+b);
                return a+b;
            },(c,d)->{
                System.out.println(c.getClass()+"   "+Thread.currentThread().getName()+"c: "+c);
                System.out.println(d.getClass()+"   "+Thread.currentThread().getName()+"d: "+d);
                return c+d;
            }));//12345
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    从这里可以看出这里改变了a的类型为String,因为我传入了一个空字符串,且最后的结果为12345,第三个参数组合器仍然不起作用,因为这里使用的是普通流。
    3,演示并行流返回类型是流中类型

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(100);//1,2,3,4,5
            System.out.println(iterate.parallel().reduce(0,(a,b)->{
                System.out.println(Thread.currentThread().getName()+"a: "+a);
                System.out.println(Thread.currentThread().getName()+"b: "+b);
                return a+b;
            },(c,d)->{
                System.out.println(Thread.currentThread().getName()+"c: "+c);
                System.out.println(Thread.currentThread().getName()+"d: "+d);
                return c+d;
            }));//5050
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    可以看出创建了15条线程用于并行计算,转换为并行流后第三个参数方法才会执行
    4,演示并行流返回类型不是流中类型

    Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5
            System.out.println(iterate.parallel().reduce("",(a,b)->{
                System.out.println(a.getClass()+"   "+Thread.currentThread().getName()+"a: "+a);
                System.out.println(b.getClass()+"  "+Thread.currentThread().getName()+"b: "+b);
                return a+b;
            },(c,d)->{
                System.out.println(c.getClass()+"   "+Thread.currentThread().getName()+"c: "+c);
                System.out.println(d.getClass()+"   "+Thread.currentThread().getName()+"d: "+d);
                return c+d;
            }));//12345
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    在这里插入图片描述
    可以看到只有b参数对应的位置数据类型为Integer,a,c,d都是String。
    在我测试过程中还想要研究两个方法分别执行了多少次的时候,发现:流中有多少元素累加器就执行多少次,但是组合器的执行次数难以琢磨。
    且最后的累加结果是很有规律的,并不是乱序。
    在这里插入图片描述

  • 相关阅读:
    Hive安装教程-Hadoop集成Hive
    你的 Python 代码太慢了吗?协程和多线程来拯救!
    C#接口多继承的写法
    C. Friends and Gifts
    zabbix
    解决两个MySQL5.7报错
    秋招每日一题T14——将矩阵按对角线排序
    前端开发如何做新手引导
    在Linux上安装RStudio工具并实现本地远程访问【内网穿透】
    Paraverse白皮书发布,打造面向3D数字资产的去中心化运行与交易平台
  • 原文地址:https://blog.csdn.net/lc257/article/details/126528823