java8 reduce的用法_Java 8系列之Stream中万能的reduce用法说明

java8 reduce的用法_Java 8系列之Stream中万能的reduce用法说明reduce操作可以实现从Stream中生成一个值,其生成的值不是随意的,而是根据指定的计算模型。比如,之前提到count、min和max方法,因为常用而被纳入标准库中。事实上,这些方法都是reduce操作。reduce方法有三个override的方法:Optionalreduce(BinaryOperatoraccumulator);Treduce(Tidentity,BinaryO…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

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

reduce方法有三个override的方法:

Optional reduce(BinaryOperator accumulator);

T reduce(T identity, BinaryOperator accumulator);

U reduce(U identity,BiFunction accumulator,BinaryOperator combiner);

我们先看第一个变形,其接受一个函数接口BinaryOperator,而这个接口又继承于BiFunction.在BinaryOperator接口中,又定义了两个静态方法minBy和maxBy。这里我们先不管这两个静态方法,先了解reduce的操作。

@FunctionalInterface

public interface BinaryOperator extends BiFunction {

public static BinaryOperator minBy(Comparator super T> comparator) {

Objects.requireNonNull(comparator);

return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;

}

public static BinaryOperator maxBy(Comparator super T> comparator) {

Objects.requireNonNull(comparator);

return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;

}

}

在使用时,我们可以使用Lambada表达式来表示

BinaryOperator接口,可以看到reduce方法接受一个函数,这个函数有两个参数,第一个参数是上次函数执行的返回值(也称为中间结果),第二个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数。要注意的是:第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素。这个方法返回值类型是Optional,

Optional accResult = Stream.of(1, 2, 3, 4)

.reduce((acc, item) -> {

System.out.println(“acc : ” + acc);

acc += item;

System.out.println(“item: ” + item);

System.out.println(“acc+ : ” + acc);

System.out.println(“——–“);

return acc;

});

System.out.println(“accResult: ” + accResult.get());

System.out.println(“——–“);

// 结果打印

——–

acc : 1

item: 2

acc+ : 3

——–

acc : 3

item: 3

acc+ : 6

——–

acc : 6

item: 4

acc+ : 10

——–

accResult: 10

——–

6814e37504bb7716845606dccb8d6b8c.png

下面来看第二个变形,与第一种变形相同的是都会接受一个BinaryOperator函数接口,不同的是其会接受一个identity参数,用来指定Stream循环的初始值。如果Stream为空,就直接返回该值。另一方面,该方法不会返回Optional,因为该方法不会出现null。

int accResult = Stream.of(1, 2, 3, 4)

.reduce(0, (acc, item) -> {

System.out.println(“acc : ” + acc);

acc += item;

System.out.println(“item: ” + item);

System.out.println(“acc+ : ” + acc);

System.out.println(“——–“);

return acc;

});

System.out.println(“accResult: ” + accResult);

System.out.println(“——–“);

// 结果打印

acc : 0

item: 1

acc+ : 1

——–

acc : 1

item: 2

acc+ : 3

——–

acc : 3

item: 3

acc+ : 6

——–

acc : 6

item: 4

acc+ : 10

——–

accResult: 10

——–

从打印结果可以看出,reduce前两种变形,因为接受参数不同,其执行的操作也有相应变化:

变形1,未定义初始值,从而第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素

变形2,定义了初始值,从而第一次执行的时候第一个参数的值是初始值,第二个参数是Stream的第一个元素

对于第三种变形,我们先看各个参数的含义,第一个参数返回实例u,传递你要返回的U类型对象的初始化实例u,第二个参数累加器accumulator,可以使用二元?表达式(即二元lambda表达式),声明你在u上累加你的数据来源t的逻辑,例如(u,t)->u.sum(t),此时lambda表达式的行参列表是返回实例u和遍历的集合元素t,函数体是在u上累加t,第三个参数组合器combiner,同样是二元?表达式,(u,t)->u。

在官方文档上有这么一段介绍,

U result = identity;

for (T element : this stream)

result = accumulator.apply(result, element)

return result;

but is not constrained to execute sequentially.

The identity value must be an identity for the combiner function. This means that for all u, combiner(identity, u) is equal to u. Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:

combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)

因为reduce的变形的第一个参数类型是实际返回实例的数据类型,同时其为一个泛型也就是意味着该变形的可以返回任意类型的数据。从上面文档介绍的字面意思解读是第三个参数函数用来组合两个值,而这两个值必须与第二个函数参数相兼容,也就是说它们所得的结果是一样的。看到这里肯定有迷惑的地方,第三个参数到底是用来干嘛的?我们先看一段代码,为了便于了解其中的缘由,并没有使用Lambda表达式,

ArrayList accResult_ = Stream.of(1, 2, 3, 4)

.reduce(new ArrayList(),

new BiFunction, Integer, ArrayList>() {

@Override

public ArrayList apply(ArrayList acc, Integer item) {

acc.add(item);

System.out.println(“item: ” + item);

System.out.println(“acc+ : ” + acc);

System.out.println(“BiFunction”);

return acc;

}

}, new BinaryOperator>() {

@Override

public ArrayList apply(ArrayList acc, ArrayList 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_);

// 结果打印

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

accResult_: [1, 2, 3, 4]

accResult_: 10

首先示例代码中,传递给第一个参数是ArrayList,在第二个函数参数中打印了“BiFunction”,而在第三个参数接口中打印了函数接口中打印了”BinaryOperator“.可是,看打印结果,只是打印了“BiFunction”,而没有打印”BinaryOperator“,说明第三个函数参数病没有执行。这里我们知道了该变形可以返回任意类型的数据。

对于第三个函数参数,为什么没有执行,刚开始的时候也是没有看懂到底是啥意思呢,而且其参数必须为返回的数据类型?看了好几遍文档也是一头雾水。

在 java8 reduce方法中的第三个参数combiner有什么作用?

3466d3c0aa24b4699d0274da478e063f.png

acd0a9d5c3be6451a962b17c71401ced.png

这里找到了答案,Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result,combiner的作用在于合并每个线程的result得到最终结果。

这也说明了了第三个函数参数的数据类型必须为返回数据类型了。

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

以上这篇Java 8系列之Stream中万能的reduce用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/230745.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(2)


相关推荐

  • 数据库原理笔记「建议收藏」

    数据库原理笔记「建议收藏」数据库概念数据库(Database,简称DB)是长期储存在计算机内、有组织的、可共享的大量数据的集合。数据库系统的特点数据结构化数据的共享性高,冗余度低,易扩充数据独立性高数据由DBMS统

  • 【iOS安全】App Store 应用爬取「建议收藏」

    【iOS安全】App Store 应用爬取「建议收藏」AppStore应用爬取

  • Android Studio 自带的虚拟机上网解决方案,100%成功

    Android Studio 自带的虚拟机上网解决方案,100%成功3个步骤执行以下步骤前先关闭你的虚拟机执行以下步骤前先关闭你的虚拟机执行以下步骤前先关闭你的虚拟机1.使用cmd进入SDK\emulator目录2.获取你的虚拟机名称emulator.exe-list-avds3.设置网关emulator.exe-avd你的虚拟机名称-dns-server8.8.8.8114.114.114.114也可。然后第三步执行完虚拟机启动就可以上网了…

  • layui table样式_layui table 分页

    layui table样式_layui table 分页table的结构:       序号   登录账号   用户名   权限   操作          ${(user.id)!”}   ${(user.userAccount!”)}   ${(user.userName!”)}   ${(user.

  • Opengles2.0入门「建议收藏」

    Opengles2.0入门「建议收藏」一二三四Opengles2.0渲染管线简单画图步骤着色器语言简单介绍镜像技术一OpenGLES2.0渲染管线1.基本处理初始化3D空间中物体的顶点坐标,顶点对应的颜色,顶点的纹

  • mos管基本开关电路_380v三根火线各是多少v

    mos管基本开关电路_380v三根火线各是多少vMOS管主要是由Metal(金属)、Oxide(氧化物)、Semiconductor(半导体)通过特殊工艺制成和三极管(电流控制电流型器件)相比,MOS管(电压控制电流型器件)具有栅极驱动基本不需要电流,损耗小、噪声低、抗辐射能力强、输入阻抗高、结构简单、便于集成和热稳定性好等优点MOSFET可以被制造成P沟道和N沟道两大类,每一类又分为增强型或者耗尽型,所以MOSFET有四种:N沟道增强型MOSFET、N沟道耗尽型MOSFET、P沟道增强型MOSFET、P沟道耗尽型MOSFET

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号