Java Stream reduce()详解

news2024/10/10 11:24:34

reduce() 是 Java Stream API 中的一个终端操作,它用于将流中的元素逐个结合起来,生成一个值。换句话说,reduce() 通过对流中的元素应用二元运算(一个接收两个输入参数并返回一个结果的操作),将多个元素“归约”成一个值。

1. reduce() 方法的作用

reduce() 用于从流中生成单一结果,常见的用途有:

  • 计算总和、乘积
  • 计算最大值、最小值
  • 将字符串、对象等组合成一个结果

reduce() 操作接受两个参数:

  1. 一个初始值(称为“标识”)。
  2. 一个二元运算符,通常以 lambda 表达式的形式提供。

最终结果是一个 Optional 值,表示该流的归约结果。常用的重载形式如下:

2. reduce() 方法的三种重载形式

形式一:reduce(BinaryOperator<T> accumulator)

这个形式没有初始值,流的第一个元素将作为初始值。返回的是 Optional<T>,以防流为空。

Optional<Integer> sum = list.stream()
                            .reduce((a, b) -> a + b);
形式二:reduce(T identity, BinaryOperator<T> accumulator)

这个形式有初始值 identity,可以保证即使流为空也会有一个默认结果。返回的是 T

int sum = list.stream()
              .reduce(0, (a, b) -> a + b);
形式三:reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator<U> combiner)

这个形式适用于并行流操作,它可以通过两个函数实现累加器和合并器的分离。通常用于并行执行任务时,按块操作进行合并。

int sum = list.parallelStream()
              .reduce(0, 
                      (partialResult, element) -> partialResult + element, // 累加器
                      Integer::sum); // 合并器

3. reduce() 的示例

让我们通过几个具体示例来理解 reduce() 的用法。

1. 计算总和

假设我们有一个整数列表,想通过 reduce() 计算所有整数的总和:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 使用有初始值的 reduce
int sum = numbers.stream()
    .reduce(0, (a, b) -> a + b);  // 初始值为 0

System.out.println(sum);  // 输出:15

解释

  • reduce(0, (a, b) -> a + b):这里 0 是初始值,(a, b) -> a + b 是累加器,流中的每个元素与前面的计算结果累加,得到最终的总和。
2. 计算乘积

你还可以用 reduce() 计算所有元素的乘积。假设我们想要计算一个整数列表的乘积:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int product = numbers.stream()
    .reduce(1, (a, b) -> a * b);  // 初始值为 1

System.out.println(product);  // 输出:120

解释

  • reduce(1, (a, b) -> a * b):初始值是 1(因为乘法的单位元素是 1),然后通过累乘计算所有元素的乘积。
3. 字符串连接

假设我们有一组字符串,想通过 reduce() 将它们连接起来,生成一个长字符串。

List<String> words = Arrays.asList("Hello", "World", "Stream", "API");

String result = words.stream()
    .reduce("", (a, b) -> a + " " + b);  // 初始值为空字符串

System.out.println(result);  // 输出:" Hello World Stream API"

解释

  • reduce("", (a, b) -> a + " " + b):初始值是空字符串 "",通过将每个单词添加到之前的字符串后面,生成最终的结果。
4. 找出最大值

假设我们想找到一个整数列表中的最大值:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int max = numbers.stream()
    .reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b);  // 初始值为 Integer.MIN_VALUE

System.out.println(max);  // 输出:5

解释

  • reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b):初始值是 Integer.MIN_VALUE,表示最小的可能值。通过比较流中的每个元素,最终找到最大的那个。
5. 找出最小值

类似地,我们可以用 reduce() 找到最小值:

int min = numbers.stream()
    .reduce(Integer.MAX_VALUE, (a, b) -> a < b ? a : b);  // 初始值为 Integer.MAX_VALUE

System.out.println(min);  // 输出:1

4. 无初始值的 reduce()

如果流为空,且使用无初始值的 reduce(),返回的将是一个 Optional 对象。这是因为如果流为空,没有值可供“归约”,因此结果是空的。

示例:
List<Integer> emptyList = new ArrayList<>();

Optional<Integer> result = emptyList.stream()
    .reduce((a, b) -> a + b);  // 没有初始值

System.out.println(result);  // 输出:Optional.empty

解释

  • 因为 emptyList 是空的,没有初始值,因此 reduce() 返回一个空的 Optional 对象,表示没有可供“归约”的元素。

5. 并行流中的 reduce()

在并行流中(parallelStream()),reduce() 可以通过第三种重载方法来高效处理大数据集。它将流拆分成多个子流,并通过累加器和合并器进行并行处理。

并行流中的示例:
int sum = numbers.parallelStream()
    .reduce(0, (partialResult, element) -> partialResult + element, Integer::sum);

System.out.println(sum);  // 输出:15

解释

  • reduce(0, (partialResult, element) -> partialResult + element, Integer::sum):这里的累加器是 (partialResult, element) -> partialResult + element,合并器是 Integer::sum,它们帮助在并行流中将多个子流的结果合并。

6. reduce() 与其他终端操作的对比

  • collect():用于将流的元素收集到一个集合中,比如 ListSetMap
  • forEach():用于遍历流中的每个元素,进行操作,但不返回结果。
  • count():用于统计流中的元素数量。

reduce() 则是将流中的所有元素“归约”成单一的结果,它不用于收集或遍历,而是用于生成某个聚合值。

总结

  • reduce() 是一个用于对流中的元素进行聚合或“归约”的操作。
  • 它将流中的多个元素通过二元运算符逐一结合,生成一个单一结果。
  • 典型用法包括求和、乘积、字符串连接、查找最大值和最小值。
  • 在使用无初始值的 reduce() 时,结果会是 Optional,以防流为空。
  • 在并行流中,reduce() 可以通过累加器和合并器并行处理大数据。

通过 reduce(),你可以非常灵活地对流中的数据进行复杂的聚合操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网约巴士订票系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;巴士信息管理&#xff0c;积分兑换管理&#xff0c;积分纪录管理&#xff0c;新闻信息管理&#xff0c;基础数据管理 微信端账号功能包括&#xff1a;系统…

国产长芯微LDC8531低功耗轨到轨输出 16 位串行输入数模转换器完全P2P替代DAC8531

描述 LDC8531是一款低功耗、单16位缓冲电压输出数模转换器&#xff08;DAC&#xff09;。其片上精密输出放大器允许实现轨到轨输出摆动。LDC8531使用多功能三线串行接口&#xff0c;其时钟频率高达30MHz&#xff0c;与标准SPI、QSPI、Microwire和数字信号处理器&#xff08;DSP…

数据库迁移中的权限问题及解决方法——以Error 1142为例

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

无线领夹麦克风哪个降噪好?选购领夹麦克风需注意的五大隐藏风险

不知道大家有没有遇到这样一个情况&#xff0c;为什么有些视频或直播的声音听起来那么清晰&#xff0c;仿佛身临其境&#xff0c;而自己拍的视频却总是嘈杂不堪&#xff0c;尤其是在户外拍摄的时候&#xff0c;音频中更是充斥着各种各样的噪音。这种问题主要还是麦克风的原因所…

3dmax笔记-ALT X 透明度设置

1 降低max的模型的透明度 ALTX 看区别 区别对比

Sentinel最全笔记,详细使用步骤教程清单

一、Sentinel的基本功能 1、流量控制 流量控制在网络传输中是一个常用的概念&#xff0c;它用于调整网络包的发送数据。然而&#xff0c;从系统稳定性角度考虑&#xff0c;在处理请求的速度上&#xff0c;也有非常多的讲究。任意时间到来的请求往往是随机不可控的&#xff0c;…

分辨率提高4到8倍!AI高清修复工具-upscayl使用方法!

你还在为手中的模糊照片苦恼吗&#xff1f; 是不是想把老照片或低分辨率的图片用于大尺寸印刷&#xff0c;却因为画质糟糕而无从下手&#xff1f; 现在你不再需要高深的Photoshop技能&#xff0c;也不用花费巨资找人修图。借助AI高清修复工具Upscayl&#xff0c;只需几秒钟&am…

一文解读数据中台附搭建指南

数据是企业的核心资产&#xff0c;更是企业数字化转型的关键驱动力。为了更好地管理和利用数据&#xff0c;进行数据共享&#xff0c;充分发挥数据的作用&#xff0c;越来越多的企业开始构建实时数据中台。 一数据中台 定义&#xff1a;数据中台是将企业内部各个部门、系统、应…

【嵌入式软件-STM32】STM32简介

目录 一、STM32定义 二、STM32用途 三、STM32特点 四、STM32 四个系列 五、了解ARM 六、芯片解释 七、片上资源 八、命名规则 九、系统结构 内核 Flash DMA 外设种类和分布 十、引脚定义 类型 名称 引脚 十一、启动配置 十二、STM32最小系统电路 STM32及供电 供电引脚 滤波电容…

机器人动力学和轨迹规划

路径规划&#xff08;way&#xff09;&#xff1a;规划连接位置A与位置B间序列点或曲线的策略。 注意&#xff1a;这个路径规划是非常重要的&#xff0c;是机器人智能的一个体现。 路径规划主要有3个方法&#xff1a;MoveJ&#xff1a;关节点到点运动&#xff0c;MoveL&#…

Spring Boot学习资源库:Java开发者的新篇章

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

crossover和虚拟机哪个好用?Mac电脑玩游戏用哪个软件?

由于大多数热门游戏都是针对Windows平台开发的&#xff0c;这对于Mac用户来说可能会带来一些困扰。幸运的是&#xff0c;有几款虚拟机软件可以帮助解决这个问题&#xff0c;其中最常提到的是Parallels Desktop&#xff08;简称PD虚拟机&#xff09;和CrossOver。 PD虚拟机&…

Nodejs-Nestjs框架 RBAC(基于角色的访问控制模型) 微服务 仿小米商城实战视频教程-2024年-试看学习记录

文章目录 前提-安装环境Nestjs框架介绍Nestjs框架环境搭建创建nestjs项目运行nestjs项目demonestjs新项目结构解释nestjs中的控制器、路由、Get、Post、方法参数装饰器nestjs模板引擎、配置静态资源(了解即可)nestjs中的服务(Model)nestjs中的cookie(了解即可)nestjs中的se…

企业工作者如何提高对数据治理的认知度

提高对数据治理的认知度是一个涉及多方面努力的过程&#xff0c;以下是一些建议&#xff0c;可以帮助企业或个人增强对数据治理的理解和重视&#xff1a; 一、教育与培训 组织内部培训&#xff1a;定期举办数据治理相关的培训课程&#xff0c;邀请行业专家或内部资深人士进行…

AI用得好,升职加薪早

最近&#xff0c;K哥在公司里经常说的一句话就是&#xff1a;“AI用得好&#xff0c;升职加薪早&#xff01;” 而且我们团队每个人都增加了一条KPI&#xff0c;叫做“含AI量”。什么意思呢&#xff1f;就是完成一项工作&#xff0c;使用了多少AI工具。 我不仅这样要求团队&…

JS 数组去重 — 各类场景适合方法大全

JS 数组去重 — 各类场景适合方法大全 本文介绍各种场景 JS 去重 方法使用 性能最好、用的最多、场景大全 文章目录 JS 数组去重 — 各类场景适合方法大全 一、基础篇&#xff1a;简单直观的去重方法1. 使用Set数据结构2. 利用filter和indexOf方法3. reduce方法的应用 二、进阶…

国产长芯微LDC5422单通道、16位、电流源和电压输出DAC,HART连接完全P2P替代AD5422

描述 LDC5422是低成本、精密、完全集成、16位数模转换器(DAC)&#xff0c;内置可编程电流源和可编程电压输出&#xff0c;设计用于满足工业过程控制应用的需要。 输出电流范围可编程设置为4 mA至20 mA、0 mA至20 mA或者超量程的0 mA至24 mA。 此产品的LFCSP版本有一个CAP2引脚…

Linux运维_安全狗Apache版本安装

--------->安全狗官网(网站安全狗-网站安全防护,防后门|防SQL注入|防CC攻击|网马查杀|防篡改) 1.下载解压安全狗 2.

《Windows PE》4.3 延迟加载导入表

延迟加载导入表&#xff08;Delayed Import Table&#xff09;是PE文件中的一个数据结构&#xff0c;用于实现延迟加载&#xff08;Lazy Loading&#xff09;外部函数的机制。 延迟加载是指在程序运行时&#xff0c;只有当需要使用某个外部函数时才进行加载和绑定&#xff0c;…

【最新华为OD机试E卷-支持在线评测】最小的调整次数(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…