首页 > 编程语言 >java8新特性-引用流-reduce

java8新特性-引用流-reduce

时间:2023-03-19 10:44:25浏览次数:37  
标签:BinaryOperator ReducingSink reduce public state 引用 new java8

reduce操作用于对数据进行聚合,比如求和等。

一、reduce(BinaryOperator accumulator)
 

例子:

List<User> users = new ArrayList<>();
users.add(new User("张三",30));
users.add(new User("李四",39));
users.add(new User("王五",20));

Optional<Integer> reduce = users.stream().map(User::getAge).reduce((a, b) -> a + b);
System.out.println(reduce.get());

输出:

 

源码分析:
ReferencePipeline#reduce(BinaryOperator<P_OUT> accumulator)

 public final Optional<P_OUT> reduce(BinaryOperator<P_OUT> accumulator) {
    return evaluate(ReduceOps.makeRef(accumulator));
}

进入ReduceOps.makeRef(BinaryOperator operator)方法。
 

ReduceOps#makeRef(BinaryOperator operator)

public static <T> TerminalOp<T, Optional<T>>
makeRef(BinaryOperator<T> operator) {
    Objects.requireNonNull(operator);
    class ReducingSink
            implements AccumulatingSink<T, Optional<T>, ReducingSink> {
        private boolean empty;
        private T state;

        public void begin(long size) {
            empty = true;
            state = null;
        }

        @Override
        public void accept(T t) {
            if (empty) {
                empty = false;
                state = t;
            } else {
                state = operator.apply(state, t);
            }
        }

        @Override
        public Optional<T> get() {
            return empty ? Optional.empty() : Optional.of(state);
        }

        @Override
        public void combine(ReducingSink other) {
            if (!other.empty)
                accept(other.state);
        }
    }
    return new ReduceOp<T, Optional<T>, ReducingSink>(StreamShape.REFERENCE) {
        @Override
        public ReducingSink makeSink() {
            return new ReducingSink();
        }
    };
}

ReduceOps会调用makeSink获取Sink。begin方法设置empty和state的初始值。看看ReducingSink里的accept方法。第一次进入,empty为true,将state设置t,以后将t和state运行BinaryOperator聚合数据且将结果赋给state。如果Stream中没有元素则empty为true,state为null。

 
 
 

二、 reduce(T identity, BinaryOperator accumulator)

identity是初始值,功能和reduce(BinaryOperator accumulator )类似。

 

例子:

   List<User> users = new ArrayList<>();
   users.add(new User("张三",30));
   users.add(new User("李四",39));
   users.add(new User("王五",20));

   Integer reduce = users.stream().map(User::getAge).reduce(0,(a, b) -> a + b);
   System.out.println(reduce);

输出:

 

 

源码分析:
ReferencePipeline#reduce(final P_OUT identity, final BinaryOperator<P_OUT> accumulator)

 public final P_OUT reduce(final P_OUT identity, final BinaryOperator<P_OUT> accumulator) {
    return evaluate(ReduceOps.makeRef(identity, accumulator, accumulator));
}

进入ReduceOps.makeRef(U seed, BiFunction<U, ? super T, U> reducer, BinaryOperator<U> combiner )方法

  makeRef(U seed, BiFunction<U, ? super T, U> reducer, BinaryOperator<U> combiner) {
      Objects.requireNonNull(reducer);
      Objects.requireNonNull(combiner);
      class ReducingSink extends Box<U> implements AccumulatingSink<T, U, ReducingSink> {
          @Override
          public void begin(long size) {
              state = seed;
          }

          @Override
          public void accept(T t) {
              state = reducer.apply(state, t);
          }

          @Override
          public void combine(ReducingSink other) {
              state = combiner.apply(state, other.state);
          }
      }
      return new ReduceOp<T, U, ReducingSink>(StreamShape.REFERENCE) {
          @Override
          public ReducingSink makeSink() {
              return new ReducingSink();
          }
      };
  }

ReduceOps会调用makeSink获取Sink。ReducingSink的begin将state设置为seed,seed就是传进去的初始值。每次调用accept都会运行BiFunction将state 和 t执行聚合。

 
三、reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
第一个参数是返回值的初始值,accumulator是对Stream中每个元素执行的聚合操作,combiner是在并行流中对每个线程的执行结果进行合并。

 

例子

 List<User> users = new ArrayList<>();
 users.add(new User("张三",30));
 users.add(new User("李四",34));
 users.add(new User("王五",20));

ArrayList<User> reduce1 = users.stream().reduce(new ArrayList<User>(), (list, user) -> {
        if (user.getAge() >= 30){
            list.add(user);
        }
        System.out.println("执行accumulator");
        return list;
    }, ((users1, users2) -> {
        System.out.println("执行combiner");
        users1.addAll(users2);
        return users1;
    }));
    System.out.println(reduce1);

输出:

 
 

源码分析:
ReferencePipeline#reduce(R identity, BiFunction<R, ? super P_OUT, R> accumulator, BinaryOperator combiner)

public final <R> R reduce(R identity, BiFunction<R, ? super P_OUT, R> accumulator, BinaryOperator<R> combiner) {
    return evaluate(ReduceOps.makeRef(identity, accumulator, combiner));
}

进入ReduceOps.makeRef。

ReduceOps#makeRef

    public static <T, U> TerminalOp<T, U>
makeRef(U seed, BiFunction<U, ? super T, U> reducer, BinaryOperator<U> combiner) {
    Objects.requireNonNull(reducer);
    Objects.requireNonNull(combiner);
    class ReducingSink extends Box<U> implements AccumulatingSink<T, U, ReducingSink> {
        @Override
        public void begin(long size) {
            state = seed;
        }

        @Override
        public void accept(T t) {
            state = reducer.apply(state, t);
        }

        @Override
        public void combine(ReducingSink other) {
            state = combiner.apply(state, other.state);
        }
    }
    return new ReduceOp<T, U, ReducingSink>(StreamShape.REFERENCE) {
        @Override
        public ReducingSink makeSink() {
            return new ReducingSink();
        }
    };
}

关注ReducingSink。ReducingSink#begin将state初始化为seed,accept对Stream中的每个元素执行reducer操作。

标签:BinaryOperator,ReducingSink,reduce,public,state,引用,new,java8
From: https://www.cnblogs.com/shigongp/p/17224405.html

相关文章

  • jlink打包javaFX应用和引用第三方库处理
    操作环境说明:操作系统:windows11(linux也可以参考本文操作)jdk版本:openjdk-17+35(理论上jdk9之后都可以按本文操作,具体是否可行,未验证)javaFX版本:javafx-sdk-17.0.2本......
  • JS数组reduce()方法详解及高级技巧
        参考:https://www.cnblogs.com/webSnow/p/15262337.html......
  • React使用createContext搭配useReducer模拟Redux
    1.准备importReact,{useReducer}from'react';//import{useIntl}from'react-intl';//用于国际化后续在写入暂时无效2.用于存放数据的函数constiniti......
  • 《Hadoop Operations》读书笔记 - 2 - 第三章 MapReduce
    MapReduce,在这里实际上有两个含义,一个是一种分布式计算模型;另一个是某种特定实现,比如ApacheHadoopMapReduce。其设计目的是为了简化大规模、分布式、高容错性的数据处理应......
  • 左值引用与右值引用
    左值引用和右值引用的区别?右值引用的意义左值引用是对左值的引用,右值引用是对右值的引用左值右值的概念左值:可以在等号左边,能够取地址,并且具备名字的(左值可以放在......
  • 11、指针和引用
    指针:是一个变量,存储一个变量的地址。引用:是变量的别名。1、初始化指针定义时不必初始化,引用必须初始化。指针初始化时可为NULL,引用不能初始化为NULL。inta=1......
  • Java中的基本数据类型和引用数据类型
    一、基本数据类型:byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0short:短整型,在内存中占16位,即2个字节,取值范围-32768~32767,默认值0int:整......
  • MIT 6.824-Lab1. MapReduce 实现思路
    参考资料MapReduce论文((20221029103443-4pqvf1n"Lecture-MapReduce"))Lab1实验文档Lab1实验文档译文任务需求在一个分布式存储系统上(实验是单机),实现coord......
  • java8 Optional使用 stream filter多级过滤
    java8Optional使用streamfilter多级过滤packagecom.example.core.mydemo.java8;publicclassMyModel{privateStringcouponCode;privateIntegeror......
  • JAVA8 lambda中map和flatMap
     lambda中map是对流元素进行转换,flatMap是对流中的元素(集合)进行平铺后合并,即对流中的每个元素平铺后又转换成为了Stream流。 flatMap首先将一个函数应用于元素,然后......