文章目录

  • Pre
    • 什么是归约操作
      • 元素求和 reduce
      • reduce如何运行的
      • 最大值和最小值


Pre

Java 8 - Stream流骚操作解读见到过的终端操作都是返回一个 boolean ( allMatch 之类的)、 void( forEach )或 Optional 对象( findAny 等)。也见过了使用 collect 来将流中的所有元素组合成一个 List 。

我们这里将学会如何把一个流中的元素组合起来,使用 reduce 操作来表达更复杂的查询,比如“计算菜单中的总卡路里”或“菜单中卡路里最高的是哪一个”。


什么是归约操作

此类查询需要将流中所有元素反复结合起来,得到一个值,比如一个 Integer 。这样的查询可以被为归约操作 (将流规约成一个值)

用函数式编程语言的术语来说,这称为折叠(fold),因为你可以将这个操作看成把一张长长的纸(你的流)反复折叠成一个小方块,而这就是规约操作的结果。

元素求和 reduce

在我们研究如何使用 reduce 方法之前,先来看看如何使用 for-each 循环来对数字列表中的元素求和

int sum = 0;
for (int x : numbers) {sum += x;
}

numbers 中的每个元素都用加法运算符反复迭代来得到结果。通过反复使用加法,你把一个数字列表归约成了一个数字。这段代码中有两个参数

  • 总和变量的初始值,在这里是 0
  • 将列表中所有元素结合在一起的操作,在这里是 + 。

要是还能把所有的数字相?,而不必去复制粘贴这段代码,岂不是很好?这正是 reduce 操作的用武之地,它对这种重复应用的模式做了抽象。你可以像下面这样对流中所有的元素求和:

int sum = numbers.stream().reduce(0, (a, b) -> a + b);

reduce 接受两个参数:

  • 一个初始值,这里是0;
  • 一个 BinaryOperator 来将两个元素结合起来产生一个新值,这里我们用的是 lambda (a, b) -> a + b

你也很容易把所有的元素相?,只需要将另一个Lambda: (a, b) -> a * b 传递给 reduce操作就可以了

int product = numbers.stream().reduce(1, (a, b) -> a * b);

我们把demo完善一下

   public static void reduce(){List<Integer> list = Arrays.asList(11,2,3);int sum = list.stream().reduce(0, (a, b) ->a+b);System.out.println(sum);int cal = list.stream().reduce(1,(a, b) ->a*b);System.out.println(cal);}

展示了 reduce 操作是如何作用于一个流的:Lambda反复结合每个元素,直到流被归约层一个新的值。


reduce如何运行的

我们深入研究一下 reduce 操作是如何对一个数字流求和的。

  • 首先, 0 作为Lambda( a )的第一个参数,从流中获得 4 作为第二个参数( b ), 0 + 4 得到 4 ,它成了新的累积值。
  • 然后再用累积值和流中下一个元素 5 调用Lambda,产生新的累积值 9 。
  • 接下来,再用累积值和下一个元素 3调用Lambda,得到 12 。
  • 最后,用 12 和流中最后一个元素 9 调用Lambda,得到最终结果 21

你可以使用方法引用让这段代码更简洁。在Java 8中, Integer 类现在有了一个静态的 sum方法来对两个数求和,这?好是我们想要的,用不着反复用Lambda写同一段代码了:

    public static void reduce(){List<Integer> list = Arrays.asList(11,2,3);int sum = list.stream().reduce(0,Integer::sum);System.out.println(sum);}

【无初始值】

reduce 还有一个重载的变体,它不接受初始值,但是会返回一个 Optional 对象:

Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));

为什么它返回一个 Optional 呢?考虑流中没有任何元素的情况。 reduce 操作无法返回其和,因为它没有初始值。这就是为什么结果被包?在一个 Optional 对象里,以表明和可能不存在。


最大值和最小值

原来,只要用归约就可以计算最大值和最小值了!让我们来看看如何利用??学到的 reduce来计算流中最大或最小的元素。

reduce 接受两个参数:

  • 一个初始值
  • 一个Lambda来把两个流元素结合起来并产生一个新值

Lambda是一步步用加法运算符应用到流中每个元素上的, 。因此,你需要一个给定两个元素能够返回最大值的Lambda。 reduce 操作会考虑新值和流中下一个元素,并产生一个新的最大值,直到整个流消耗完

可以像下面这样使用 reduce 来计算流中的最大值

Optional<Integer> max = numbers.stream().reduce(Integer::max);

要计算最小值,你需要把 Integer.min 传给 reduce 来替换 Integer.max :

Optional<Integer> min = numbers.stream().reduce(Integer::min);

Java 8 - Stream流骚操作解读2_归约操作相关推荐

  1. Java 8 - Stream流骚操作解读

    文章目录 分类 中间操作 终端操作 使用Stream流 筛选和切片 用谓词筛选 filter 筛选各异的元素 distinct 截短流 limit 跳过元素 skip 映射 对流中每一个元素应用函数 ...

  2. Java 8 Stream 流用法及语法

    Java 8 Stream 流用法 1.简介 Stream流 最全的用法 Stream 能用来干什么?用来处理集合,通过 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据 ...

  3. 函数式编程(JAVA)——Stream流

    函数式编程(JAVA)--Stream流 概述 Java8的Stream使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作.可以更方便的让我们对集合或数组操作. 下述 ...

  4. Java基础 Stream流方法引用异常文件

    Stream流 引例 需求:按照下面要求完成集合的创建和遍历 创建一个集合,存储多个字符串元素 1. 把所有以"曹"开头的元素存储到新集合中 2. 把曹开头,长度为3的元素存储到新 ...

  5. Java 8 Stream流 的用法

    Java 8 Stream流 什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 元素是特定类型的对象,形成一个队列. Java中的Stream并不会存储元素,而是按需 ...

  6. 对比Java的Stream流和C# 的Linq

    Java由于没有委托的概念,所以用函数式接口 @FunctionalInterface 与 lambda表达式相结合,实现了类似于C# 中委托,C++中函数指针的功能. 函数指针/委托在Java中被命 ...

  7. [Java基础]Stream流的收集操作

    代码如下: package CollectPack;import java.util.*; import java.util.stream.Collectors; import java.util.s ...

  8. JAVA的stream流操作详细解析

    java的stram流操作 为什么需要 Stream 流与集合的区别 对比:原始集合操作与Stream集合操作 (过滤/映射/扁平化/遍历/排序/去重/跳过/截断的应用) 流的组成 流操作的分类 流的 ...

  9. Java 8 Stream流的常见操作

    Stream流的使用 在 Java 8 中, 集合接口有两个方法来生成流: stream() − 为集合创建串行流.parallelStream() − 为集合创建并行流. 串行流 如果是数组的话,可 ...

最新文章

  1. Java黑皮书课后题第8章:**8.14(探讨矩阵)编写程序,提示用户输入一个方阵的长度,随机地在矩阵中填入0和1,打印这个矩阵,然后找出整行、整列或者对角线都是1或0的行、列和对角线
  2. IBM DW上关于SOA的规范归纳
  3. 程序实践:命令行之连连看
  4. java学习(10):数据类型
  5. java redis 故障切换_java使用Redis6–sentinel单点故障主从自动切换
  6. [No000014]听说不背单词,考英语会是这种下场-我们为什么必须背单词?
  7. Spring源码分析-Spring事务源码分析
  8. 华为手机相册怎么镜像翻转_怎么制作照片视频?利用手机相册快速制作卡点视频...
  9. iOS游戏开发之Game Center研究
  10. Cell | 共生菌群通过γδ T细胞促进肺癌的发展
  11. XP系统常用的登录密码方法破解(一共9种)
  12. Day2快捷键+简单Dos命令
  13. bs文件服务器,BS在线文件管理系统
  14. 产品介绍 | 51LA短链分发平台
  15. java计算机毕业设计ssm基于Vue的二手商品交易网站z40n1(附源码、数据库)
  16. FastDFS分布式文件系统实践详解
  17. oracle判断是否是手机号码,oracle存储过程判断手机号码和固话
  18. Mybatis Generator逆向工程的使用
  19. (胡闹) RISC CSDN
  20. 使用iptables实现主机防火墙隔离

热门文章

  1. html隐藏目录在哪里查找,使用Dirsearch查找隐藏目录
  2. CV之路 —— Opencv学习
  3. Unbutu下安装mysql服务并允许远程登录
  4. nginx 超时时间_我眼中的 Nginx(四):是什么让你的 Nginx 服务退出这么慢?
  5. python gil_Python GIL(Global Interpreter Lock)
  6. gtk移植到嵌入式_物联网时代的盛行,应届毕业生是学嵌入式好呢,还是安卓或ios呢?...
  7. 85. Leetcode 746. 使用最小花费爬楼梯 (动态规划-基础题)
  8. MATLAB从入门到精通-matlab计算多重复杂多边形重叠面积
  9. 澳洲森林火灾蔓延数学建模,基于元胞自动机模拟多模式下火灾蔓延(附部分源码)
  10. arp欺骗攻击——获取内网中用户浏览的图片信息