Java Lambda从入门到精通十四 流的使用-规约

说起规约,有的同学可能不太理解,我们先来说一下概念。相信大多数开发同学都听说过hadoop,前几年非常火的一个技术就是大数据,而hadoop是大数据的入门技术,其中就有一个关键概念map-reduce,意思就是分-总计算,简单来说就是将要计算的数据分散到多个独立单元(可以理解为按照任务大小拆分任务到多台计算机执行计算)中计算,每个单元计算出结果后,再进行结果汇总,从而突破单机性能瓶颈,这个汇总的动作就是规约,也就reduce。

在实际应用中,我们经常要用到将一组数据的值进行累加汇总,得到一个总和,lambda中也支持这样的操作,就是reduce()函数。

当然,规约的概念并不是仅限于求和,凡是要将一组值合起来,再求出一个值的操作,都是规约,比如我求最大值、最小值等。

来看demo代码

初始化测试数据:

        List<Student> list = new ArrayList<>();
        String[] names = {"小明","小华","小志","小东","小李","小张","小王","小周","小吴","小郑"};
        for(int i=0; i<10; i++) {
            Student student = Student.builder()
                    .name(names[i])
                    .age(12+i/5)
                    .no(i+1)
                    .math(85d+i).build();
            list.add(student);
        }
        System.out.println("======初始化数据:======");
        list.forEach(System.out::println);

1、reduce

求班级学生数据成绩加和,我们可以使用两种写法:

double reduce = list.stream().mapToDouble(Student::getMath).reduce(0d, (x, y) -> x + y);
        System.out.println("所有学生数学成绩加和:" +reduce);

        double reduce2 = list.stream().mapToDouble(Student::getMath).reduce(Double::sum).getAsDouble();
        System.out.println("所有学生数学成绩加和:" +reduce2);

输出结果:

所有学生数学成绩加和:895.0
所有学生数学成绩加和:895.0

我们来看一下reduce方法:

T reduce(T identity,
         BinaryOperator<T> accumulator)

第一个参数就是起始值,我们求累加操作,起始值一般都是从0开始,第二个参数也是一个lambda表达式,BinaryOperator是一个二元操作,求累加,这里的表达式就是(a,b)->a+b;这两个参数配合使用就是第一参数0先和流中第一个元素相加得到的结果,再和流中第二个元素相加,这样依次和每个元素相加,最终得到求和结果。

2、求最大最小值

我们使用reduce也可以去最大和最小值,这里先看最大值:

Optional<Double> max = list.stream().map(Student::getMath).reduce(Double::max);
        System.out.println("max-所有学生数学成绩最高分:" +max.get());

Stream中也实现了一个max方法,可以直接求最大值:

Optional<Student> max2 = list.stream().max(Comparator.comparing(Student::getMath));
        System.out.println("max2-所有学生数学成绩最高分:" +max2.get().getMath());

输出结果:

max-所有学生数学成绩最高分:94.0
max2-所有学生数学成绩最高分:94.0

求最小值:

Optional<Student> min = list.stream().min(Comparator.comparing(Student::getMath));
        System.out.println("所有学生数学成绩最低分:" +min.get().getMath());

输出结果:

所有学生数学成绩最低分:85.0