在Stream流操作中,比如说min(),max(),count()方法,这几个操作都会将一个流缩减成一个值,流API将这些操作称为特例缩减。另外,流API同时泛华了缩减这种概念,提供了reduce()方法,通过使用reduce()方法,可以基于任意条件,从流中返回一个值。根据定义,所有缩减操作都是终端操作。

我们先来翻下api:

Optional<T>	reduce(BinaryOperator<T> accumulator) :Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
T reduce(T identity, BinaryOperator<T> accumulator) :Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value.
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner):Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions.

先来看一段代码演示下如果对一个流做缩减操作:

public static void main(String[] args) throws Exception
{
List<Integer> list = new ArrayList<>(4);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//reduce第一个重载,直接进行缩减
list.stream().reduce((a, b) -> a + b).ifPresent(System.out::println);
//reduce第二个重载,可以指定初始值,然后在进行缩减
System.out.println(list.stream().reduce(0, Integer::sum));
//reduce第三个重载,可以指定初始值,然后在进行缩减,第3个参数用来处理并行流的操作
System.out.println(list.stream().reduce(0, (a, b) -> a * 2 + b, (c, d) -> c + d));
List<String> list1 = Lists.newArrayList("1", "2", "3", "4");
System.out.println(list1.stream().reduce(1, (a, b) -> a + b.length(), (c, d) -> c + d));
}

这里我们重点要看下前面2个方法:

Optional<T> reduce(BinaryOperator<T> accumulator)

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

第一个方法返回一个Optional对象,该对象包含了结果。第二个方法直接返回T类型的对象,这里的这个T类型就是流中元素的类型。在使用这2个方法的时候,要传入一个Lambda表达式,这个表达式要实现BinaryOperator<T>函数式接口,先说下这个接口吧:具体的可以去看我前面有篇博客的,这些函数式接口很容易忘掉了,我晕。

public interface BinaryOperator<T> extends BiFunction<T,T,T> {}

这个函数式接口扩展了BiFunction<T,T,T> 接口,这里只不过赋值方法的参数是同一个类型,然后返回值也是同一个类型而已。对于,BinaryOperator<T> 来说,apply方法现在变成了如下方法:

T apply(T val, T value);其中val将包含前一个结果,然后value包含下一个元素。我们在调用reduce的时候,val将包含单位初始值或者第一个元素。在上面2个方法中,第一个方法将包含第一个元素,第二个方法将包含单位值。





注意:

累加器操作必须满足以下3个约束:

1,无状态

2,不干预

3,结合性

无状态意味着操作不依赖于任何状态信息,不干预意味着操作不会改变数据源,最后操作必须具有关联性。这里的关联性可以理解为加法结合律或者乘法结合律,举个例子,(a+b)+c=a+(b+c);





最后这里整理下reduce的第3个重载方法:

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

考虑如下情景:假设我们现在有一个包含多个对象的流,并且希望对他们的某个属性进行求和。例如求一个流中的所有字符串的总长度,这个时候我们没有办法用上面的2个reduce的重载,因为上面2个方法中需要一个(T,T)->T这样子的函数式接口,但是这里这2个类型是不同的,流中的元素是String的,但是累加的结果是整型的。对于这种情况,我们只能使用重载的第3个方法了。

public static void main(String[] args)
{
Stream<String> of = Stream.of("张飞", "关羽");
//一下代码报错,类型不匹配The method reduce(String, BinaryOperator<String>) in the type Stream<String>
//is not applicable for the arguments (int, BinaryOperator<String>)
of.reduce(0, (a, b) -> a + b.length());
System.out.println(of.reduce(0, (a, b) -> a + b.length(), Integer::sum));
}

流API--缩减操作的更多相关文章

  1. Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  2. 【JDK8】Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  3. 通过流的方式操作hadoop的API

    通过流的方式操作hadoop的API 功能: 可以直接用来操作hadoop的文件系统 可以用在mapreduce的outputformat中设置RecordWrite 参考: 概念理解 http:// ...

  4. java8-Stream流API

    一回顾与说明 经过前面发布的三章java8的博客,你就懂得了我们为什么要用Lamda表达式,Lamda表达式的原理与函数式接口的关系,从Lamda表达式到方法引用和构造引用. 想要学Stream流你必 ...

  5. 恕我直言你可能真的不会java第11篇-Stream API终端操作

    一.Java Stream管道数据处理操作 在本号之前写过的文章中,曾经给大家介绍过 Java Stream管道流是用于简化集合类元素处理的java API.在使用的过程中分为三个阶段.在开始本文之前 ...

  6. Python 完美诠释"高内聚"概念的 IO 流 API 体系结构

    1. 前言 第一次接触 Python 语言的 IO API 时,是惊艳的.相比较其它语言所提供的 IO 流 API . 无论是站在使用者的角度还是站在底层设计者的角度,都可以称得上无与伦比. 很多人在 ...

  7. InfluxDB学习之InfluxDB的HTTP API查询操作

    在 InfluxDB学习 的上一篇文章:InfluxDB学习之InfluxDB的HTTP API写入操作 中,我们介绍了使用InfluxDB的HTTP API进行数据写入操作的过程,本文我们再来介绍下 ...

  8. InfluxDB学习之InfluxDB的HTTP API写入操作

    HTTP API也有两种操作:写入和查询,本文就先给大家介绍一下 InfluxDB的HTTP API的写入操作方式.     在InfluxDB学习的上一篇文章:InfluxDB学习之InfluxDB ...

  9. 利用Fiddler修改请求信息通过Web API执行操作(Action)实例

    本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复261或者20170724可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...

随机推荐

  1. Android系统上如何实现easyconfig(airkiss)

    刚买回来一个智能音箱和博联,需要给音箱和博联配置联网,音箱需要先打开蓝牙,然后在手机app中填写wifi的ssid和密码,通过蓝牙发送到音箱,音箱收到后连接到wifi. 博联就比较奇怪,进入联网模式以 ...

  2. 【读书笔记】【深入理解ES6】#2-字符串和正则表达式

    更好的Unicode支持 在ES6出现以前,JS字符串一直基于16位字符编码(UTF-16)进行构建. 每16位的序列是一个编码单元(code unit),代表一个字符. length.charAt( ...

  3. Jenkins-Dingding Notification Plugin 配置

    具体内容请移步Jenkins官网或作者Github,本文仅为实践分享,记录几个小坑! 感谢插件作者的贡献! 转载注明出处:http://www.cnblogs.com/ityoung/p/648915 ...

  4. 【CentOS】阿里云CentOS安装php环境

    本文在介绍安装php环境前,已安装了nginx.mysql. 一.安装 使用国内的搜狐镜像站下载php5.6安装包,执行: wget  http://mirrors.sohu.com/php/php- ...

  5. Java与算法之(12) - 老鼠再闯迷宫(广度优先算法)

    贪吃的小老鼠又回来了,这次有什么新的办法吃到奶酪呢? 规则不变,只能上下左右在格子内移动. 因为上次的深度优先算法让老鼠走了不少冤枉路,这次老鼠带来了帮手探路鼠.探路鼠的使用规则如下: 小老鼠按右.下 ...

  6. deeplearning.ai 人工智能行业大师访谈 Pieter Abbeel 听课笔记

    1. Pieter Abbeel小时候想做一个篮球运动员 - -!上学的时候喜欢数学和物理,上大学之后很自然的学工程.Pieter定义工程问题是"解决实际中应用物理和数学的问题". ...

  7. 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】

    CSGO Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  8. TCP为什么需要3次握手与4次挥手(转载)

    为什么需要“三次握手” 在谢希仁著<计算机网络>第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”.在另一部经典的<计算机网络> ...

  9. 微信小程序监听input输入并取值

    小程序的事件分为两种,冒泡和非冒泡事件,像<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件等非冒泡 ...

  10. xshell连接虚拟机Ubuntu问题

    近期为了学习数据库的操作,准备在虚拟机中搭建环境以便操作(为什么在虚拟机搭建学习环境?),系统刚装好第一步就被阻止了. 总是会提示Could not connect to.原因是虚拟机没有安装ssh服 ...