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


第一次计算使用前两个参数,后面以上一次计算的返回值作为第一个参数,流中取下一个值作为第二个参数

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

Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 2).limit(5);//1,3,5,7,9System.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

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


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

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


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

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

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

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

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

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

回到reduce方法

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

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

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

Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5System.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

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

Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5System.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


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

Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(100);//1,2,3,4,5System.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


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

Stream<Integer> iterate = Stream.iterate(1, (a) -> a + 1).limit(5);//1,2,3,4,5System.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



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

Stream流reduce方法相关推荐

  1. Stream流、方法引用知识梳理

    Stream流.方法引用 第一章 Stream流 这里的Stream流不是IO Stream 因为Lambda引入的函数式编程在java8中有一个全新的Stream概念,用于解决已有集合类库的弊端 1 ...

  2. 2022/07/17、18 day10/11:Stream流、方法引用

    文章目录 1. Stream流 1.1 引言 1.2 流式思想概述 1.3 获取流 1.4 常用方法 1.5 练习:集合元素处理(传统方式) 1.6 练习:集合元素处理(Stream方式) 2. 方法 ...

  3. 【Stream流、方法引用】

    Java基础 第二十四章 Stream流.方法引用 今日内容 Java基础 Stream流 流与集合 传统集合的多步遍历代码 循环遍历的弊端 Stream的更优写法 流式思想概述 获取流 根据Coll ...

  4. 【Java】Stream流和方法引用

    1 Stream流 1.1 Stream流优化过滤集合 传统方式 用一个循环过滤姓张的人 用一个循环过滤名字长度大于2的人 public static void main(String[] args) ...

  5. java day24【Stream流、方法引用】

    第一章 Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定"流"就一定是"IO流"呢?在Java 8中,得益于Lambda所带来的 ...

  6. Lambda表达式,Stream流,方法引用,Base64(JDK8新特性)

    Labda表达式 Lambda表达式演示 Lanbda表达式:是JDK1.8提出的一种新语法.是对之前的某种情况的代码的"简化写法". Lambda表达式演示: public cl ...

  7. Java8 stream流map方法使用

    直接上代码,顺便演示了从匿名内部类→lamdba表达式: /*** stream流的map方法的作用* 将当前流中的元素从一种类型转换为另一种类型存储到新流中* map 方法中隐含的函数式接口是 Fu ...

  8. Java笔记_16(不可变集合、Stream流、方法引用)

    Java笔记_16 一.创建不可变集合 1.1.创建不可变集合的应用场景 1.2.创建不可变集合的书写格式 二.Stream流 2.1.体验Stream流 2.2.Stream流的思想和获取Strea ...

  9. Stream流使用方法总结

    什么是流? 流是一种处理数据的高级手段,任何数据都可以转化成流进行处理.对Stream流来说,比较常见数据源有集合.数组.IO等. 流的特点 1.只能遍历一次 我们可以把流想象成一条流水线,流水线的源 ...

最新文章

  1. Tianchi发布最新AI知识树!
  2. Java面试宝典系列之面试复习提纲
  3. php 获取agent,PHP代码 解析HTTP_USER_AGENT 获取客户端操作系统
  4. div独占一行 html_web前端基础-HTML及CSS选择器
  5. MFC小笔记:开机自动启动
  6. vue ---- 组件
  7. 如何从程序中改变音量?
  8. 浏览器访问一个地址的大概操作步骤
  9. 时间序列分析matlab_平稳时间序列分析之模型识别
  10. Python环境与PyCharm编辑器的安装教程
  11. 2022年11月骨传导耳机排名,骨传导蓝牙耳机品牌怎么选?
  12. 搞懂回溯算法,我终于能做数独了
  13. 【TF2基础教程1】结构化数据建模流程
  14. 谈谈我对华为HarmonyOS 2.0的看法
  15. 松下php研究所,松下幸之助实践经营哲学10-2
  16. 阿里巴巴牵头发起对雅虎的250亿美元并购
  17. 中概股危机未过,达达集团此时赴美IPO 凭什么?
  18. [实验室每日一题][20201124][Zip已知明文攻击]
  19. 注意力图Attention map可视化【亲测完美】
  20. 学生易语言学习第二天

热门文章

  1. Logisim的基本使用方法(详细)教你如何使用Logisim
  2. ROS下使用stm32 与rosserial进行通信的开发说明及源代码示例
  3. 动态数组(Array)
  4. java利用keytool将.cer转.keystore
  5. SVG使用XML格式定义图像
  6. oracle rac info: prif-26,Oracle RAC 常用维护工具和命令大全
  7. MSP430远程升级解决方案
  8. nnU-Net: 基于U-Net医学图像分割技术的自适应框架
  9. 【动态规划】基础DP--硬币组合
  10. Quantum Mechanic