当前位置:主页 > java教程 > JAVA8 Stream reduce()方法

JAVA8 Stream流中的reduce()方法详解

发布:2023-03-22 18:40:02 59


为网友们分享了相关的编程文章,网友仰和蔼根据主题投稿了本篇教程内容,涉及到JAVA8、Stream、reduce()方法、JAVA8、Stream、reduce、JAVA8 Stream reduce()方法相关内容,已被229网友关注,涉猎到的知识点内容可以在下方电子书获得。

JAVA8 Stream reduce()方法

reduce()简介

  • Reduce 原意:减少,缩小
  • 根据指定的计算模型将Stream中的值计算得到一个最终结果

解释reduce 操作可以实现从Stream中生成一个值,其生成的值不是随意的,而是根据指定的计算模型。比如,之前提到count、min和max方法,因为常用而被纳入标准库中。事实上,这些方法都是reduce操作。

reduce三个override的方法

reduce方法有三个override的方法:

Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
<U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);

公共集合

测试代码中的所有集合,都是该集合。 

List<Person> javaProgrammers = new ArrayList<Person>() {
        {
            add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
            add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
            add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25));
            add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
            add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25));
            add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
            add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99));
            add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
            add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14));
            add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
        }
    };

 方式一reduce(BinaryOperator accumulator)

Optional<T> reduce(BinaryOperator<T> accumulator);
我们先看第一个变形,参数列表为一个函数接口BinaryOperator<T>,
BinaryOperator源码:

 public interface BinaryOperator<T> extends BiFunction<T,T,T> {
      public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }
    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

看BinaryOperator接口源码,我们可以看到,它又继承了BiFunction<T,T,T>.
另外,在BinaryOperator接口中又定义了另个静态方法为minBy和maxBy,
上面我们提到BinaryOperator接口继承了BiFunction<T,T,T>,我们看一下BiFunction<T,T,T>源码:

 @FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);//接收两个参数 t 和 u, 返回 R
}

Bifunction中有一个apply方法,接收两个参数,返回一个结果
小结: 不管是BinaryOperator类还是最终继承的BiFunction类,在类上都有@FunctionalInterface注解,因此reduce(BinaryOperator<T> accumulator)方法需要一个函数式接口参数,该函数式接口需要两个参数,返回一个结果(reduce中返回的结果会作为下次累加器计算的第一个参数),也就是累加器,最终得到一个Optional对象

测试示例代码:

     @Test
    public void Test() {
        int asInt = javaProgrammers.stream()         .mapToInt(Person::getSalary)//返回数值流,减少拆箱封箱操作,避免占用内存  IntStream         .reduce((x, y) -> x += y)// int         .getAsInt(); //return int
        System.out.printf("方式一   reduce(BinaryOperator<T> accumulator)   求薪资测试结果:"+asInt);
 
        /*解析:
             1. reduce(BinaryOperator<T> accumulator)    reduce方法接受一个函数,这个函数有两个参数
             2. 第一个参数是上次函数执行的返回值(也称为中间结果),第二个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数
         *注意:
             1.第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素
             2.方法返回值类型是Optional
         */
    }

方式二reduce(T identity, BinaryOperator accumulator) T reduce(T identity, BinaryOperator<T> accumulator);
与第一种变形相同的是都会接受一个BinaryOperator函数接口,不同的是其会接受一个identity参数,identity参数与Stream中数据同类型,相当于一个的初始值,通过累加器accumulator迭代计算Stream中的数据,得到一个跟Stream中数据相同类型的最终结果。
测试示例代码:

     @Test
    public void test1(){
        int reduce = javaProgrammers.stream().mapToInt(Person::getSalary).reduce(10000, (x, y) -> x += y);
        System.out.printf("方式二  reduce(T identity, BinaryOperator<T> accumulator)   求薪资测试结果:"+reduce);
 
        /*注意:
         *      1.与方式一相比设置了累加器的初始值,参数一(x)则不再是Stream中的第一个数据而是设置的初始值(10000)其他相同
         */
    }

打印结果:

 方式一   reduce(BinaryOperator<T> accumulator)   求薪资测试结果:57308
方式二  reduce(T identity, BinaryOperator<T> accumulator) 求薪资测试结果:67308 //初始值10000

方式三 reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)

\<U\> U reduce(U identity,BiFunction\<U, ? super T, U\> accumulator,BinaryOperator\<U\> combiner);
我们先观察分析再次被改变的参数列表:

               1. 第一个参数:返回实例u,传递你要返回的U类型对象的初始化实例u

               2. 第二个参数:累加器accumulator,可以使用lambda表达式,声明你在u上累加你的数据来源t的逻辑,例如(u,t)->u.sum(t),此时lambda表达式的行参列表是返回实例u和遍历的集合元素t,函数体是在u上累加t

               3. 第三个参数:参数组合器combiner,接受lambda表达式。

根据参数我们一步一步分析代码示例:

@Test
    public void test2() {
        ArrayList<Integer> accResult_ = Stream.of(1, 2, 3, 4)
                //第一个参数,初始值为ArrayList
                .reduce(new ArrayList<Integer>(),
                        //第二个参数,实现了BiFunction函数式接口中apply方法,并且打印BiFunction
                        new BiFunction<ArrayList<Integer>, Integer, ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> acc, Integer item) {
      acc.add(item);     System.out.println("item: " + item);     System.out.println("acc+ : " + acc);     System.out.println("BiFunction");     return acc; } //第三个参数---参数的数据类型必须为返回数据类型,改参数主要用于合并多个线程的result值 // (Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result)
                        }, new BinaryOperator<ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> acc, ArrayList<Integer> item) {     System.out.println("BinaryOperator");     acc.addAll(item);     System.out.println("item: " + item);     System.out.println("acc+ : " + acc);     System.out.println("--------");     return acc; }
                        });
        System.out.println("accResult_: " + accResult_);
 
        System.out.println("------------------lambda优化代码-----------------");
 
        ArrayList<Integer> newList = new ArrayList<>();
 
        ArrayList<Integer> accResult_s = Stream.of(1,2,3,4)
                .reduce(newList,
                        (acc, item) -> { acc.add(item); System.out.println("item: " + item); System.out.println("acc+ : " + acc); System.out.println("BiFunction"); return acc;
                        }, (acc, item) -> null);
        System.out.println("accResult_s: " + accResult_s);
    }

         示例代码中,第一个参数是ArrayList,在第二个函数参数中打印了“BiFunction”,而在第三个参数接口中打印了函数接口中打印了”BinaryOperator“.看下面的打印结果,只打印了“BiFunction”,而没有打印”BinaryOperator“,也就是说第三个函数参数并没有执行。分析参数时我们知道了该变形可以返回任意类型的数据
        对于第三个函数参数,为什么没有执行,而且其参数必须为返回的数据类型?这是因为Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result,combiner的作用在于合并每个线程的result得到最终结果。这也说明了了第三个函数参数的数据类型必须为返回数据类型了。

java8新特性之stream流中reduce()求和知识总结

打印结果:

item: 1
acc+ : [1]
BiFunction
item: 2
acc+ : [1, 2]
BiFunction
item: 3
acc+ : [1, 2, 3]
BiFunction
item: 4
acc+ : [1, 2, 3, 4]
BiFunction

另外需要注意:因为第三个参数用来处理并发操作,如何处理数据的重复性,应多做考虑,否则会出现重复数据!

到此这篇关于JAVA8 Stream流中的reduce()方法详解的文章就介绍到这了,更多相关JAVA8 Stream reduce()方法内容请搜索码农之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持码农之家!


参考资料

相关文章

  • Flutter StreamBuilder实现局部刷新实例详解

    发布:2023-03-02

    这篇文章主要为大家介绍了Flutter StreamBuilder实现局部刷新实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • JDBC中使用Java8的日期LocalDate和LocalDateTime操作mysql、postgresql

    发布:2020-07-08

    这篇文章主要给大家介绍了关于JDBC中如何使用Java8的日期LocalDate和LocalDateTime的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下


  • Java8新特性之Collectors.joining()实例详解

    发布:2023-03-05

    在项目中我们常常要对list集合的数据做一些字符串拼接/处理等相关操作,下面这篇文章主要给大家介绍了关于Java8新特性之Collectors.joining()的相关资料,需要的朋友可以参考下


  • java8 Stream大数据量List分批处理切割方式

    发布:2023-04-04

    这篇文章主要介绍了java8 Stream大数据量List分批处理切割方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教


  • Java8简单了解Lambda表达式与函数式接口

    发布:2022-07-11

    为网友们分享了关于Java8的教程,这篇文章主要介绍了Java8简单了解Lambda表达式与函数式接口,具有一定参考价值,需要的朋友可以了解下。


  • java理论基础Stream API终端操作示例解析

    java理论基础Stream API终端操作示例解析

    发布:2022-09-07

    给网友朋友们带来一篇关于java的教程,这篇文章主要为大家介绍了java理论基础Stream API终端操作示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Spring Cloud Stream异常处理过程讲解

    发布:2020-03-25

    这篇文章主要介绍了Spring Cloud Stream异常处理过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下


  • 如何理解Java 8 新增函数式接口

    发布:2020-01-19

    这篇文章主要介绍了浅谈Java 8 新增函数式接口到底是什么,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧


网友讨论