Java Stream reduce()使用指南

 更新时间:2024年10月10日 10:45:39   作者:昕er  
reduce()是Java Stream API中的一个重要终端操作,用于将流中的元素通过二元运算符结合起来,生成单一结果,它主要用于计算总和、乘积、最大值、最小值和字符串连接等,本文给大家介绍Java Stream reduce(),感兴趣的朋友一起看看吧

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

1. reduce() 方法的作用

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

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

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

  • 一个初始值(称为“标识”)。
  • 一个二元运算符,通常以 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(),你可以非常灵活地对流中的数据进行复杂的聚合操作。

到此这篇关于Java Stream reduce()详解的文章就介绍到这了,更多相关Java Stream reduce()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java消息队列Kafka的简单概述

    Java消息队列Kafka的简单概述

    这篇文章主要介绍了Java消息队列Kafka的简单概述,消息系统负责将数据从一个应用程序传输到另一个应用程序,应用程序可以专注于数据,不担心如何共享它,需要的朋友可以参考下
    2023-07-07
  • Spring Boot 处理带文件表单的方式汇总

    Spring Boot 处理带文件表单的方式汇总

    本文详细介绍了六种处理文件上传的方式,包括@RequestParam、@RequestPart、@ModelAttribute、@ModelAttribute+@RequestPart、@RequestPart接收JSON和HttpServletRequest原生方式,每种方式都有其特点和适用场景,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • Spring框架学习常用注解汇总

    Spring框架学习常用注解汇总

    这篇文章主要为大家介绍了Spring框架学习中一些经常用的注解汇总及示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-10-10
  • 基于IDEA2018卡死不动的解决方式(好用)

    基于IDEA2018卡死不动的解决方式(好用)

    这篇文章主要介绍了基于IDEA2018卡死不动的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java实现Redisson分布式锁的10大陷阱与避坑指南

    Java实现Redisson分布式锁的10大陷阱与避坑指南

    本文介绍了Redisson分布式锁的基础用法与高级特性,包括基本锁操作、公平锁、读写锁、联锁和红锁等实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2026-04-04
  • IDEA提示内存不足 low memory的完美解决方法(亲测好用)

    IDEA提示内存不足 low memory的完美解决方法(亲测好用)

    这篇文章主要介绍了IDEA提示内存不足 low memory的完美解决方法(亲测好用),这里以IDEA2022版本为例,在IDE中 帮助(help)–>change memory setting(改变内存设置),具体设置办法文中给大家详细讲解,需要的朋友可以参考下
    2023-01-01
  • Java的三种代理模式简述

    Java的三种代理模式简述

    这篇文章主要简述Java的三种代理模式,java的代理模式主要包括静态代理、动态代理、Cglib代理,感兴趣的小伙伴可以参考下面文章的具体内容
    2021-09-09
  • SpringBoot实现对静态资源的访问权限控制的三种方案

    SpringBoot实现对静态资源的访问权限控制的三种方案

    在日常的 Spring Boot 开发中,我们通常会使用安全认证、授权手段来保护后端的 RESTful API,确保只有认证和授权的用户才能访问,所以本文就给大家介绍SpringBoot中如何实现对静态资源的访问权限控制,需要的朋友可以参考下
    2025-09-09
  • mybatis执行批量更新batch update 的方法(oracle,mysql两种)

    mybatis执行批量更新batch update 的方法(oracle,mysql两种)

    这篇文章主要介绍了mybatis执行批量更新batch update 的方法,提供oracle和mysql两种方法,非常不错,需要的朋友参考下
    2017-01-01
  • SpringMVC如何配置JSP视图解析器

    SpringMVC如何配置JSP视图解析器

    这篇文章主要介绍了SpringMVC如何配置JSP视图解析器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05

最新评论