首页 > 编程语言 >reduce 到底是什么?Java8 Stream 的终极聚合工具详解

reduce 到底是什么?Java8 Stream 的终极聚合工具详解

时间:2025-01-16 11:01:08浏览次数:1  
标签:java Stream Arrays reduce public util import Java8

reduce() 是 Java Stream API 提供的一个终端操作方法,用于将流中的元素组合起来生成一个单一的值。这一方法非常强大,可以实现累积、聚合、拼接等功能,适用于各种数据处理场景。


1. reduce() 方法的作用

reduce() 是一个通用的归约操作,它通过一个 关联函数,逐个处理流中的每个元素,将其累积为一个值。
方法签名如下:

无初始值的 reduce

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

带初始值的 reduce

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

带初始值且支持并行计算的 reduce

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

2. reduce() 的参数详解

  1. identity (初始值)

    • 归约过程的起始值。
    • 如果流为空,则直接返回此初始值。
  2. accumulator (累加器)

    • 一个函数,定义了如何将流中的元素与当前累积值结合。
  3. combiner (组合器)

    • 仅在并行流中使用,定义了如何将多个部分结果合并成一个结果。

3. 常见使用场景与示例

3.1 求和

通过 reduce() 实现流中所有元素的求和。

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用 reduce 求和
        int sum = numbers.stream()
                .reduce(0, Integer::sum); // 初始值为 0,累加操作

        System.out.println("Sum: " + sum); // 输出 15
    }
}

3.2 求最大值

利用 reduce() 找出流中的最大值。

import java.util.Arrays;
import java.util.List;

public class MaxExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(7, 2, 8, 1, 4);

        // 使用 reduce 求最大值
        int max = numbers.stream()
                .reduce(Integer.MIN_VALUE, Integer::max);

        System.out.println("Max: " + max); // 输出 8
    }
}

3.3 字符串拼接

将流中的字符串拼接为一个完整的字符串。

import java.util.Arrays;
import java.util.List;

public class StringConcatenation {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("Java", "is", "fun");

        // 使用 reduce 拼接字符串
        String result = words.stream()
                .reduce("", (s1, s2) -> s1 + " " + s2);

        System.out.println("Concatenated String: " + result.trim()); // 输出 "Java is fun"
    }
}

3.4 计算乘积

通过 reduce() 实现乘积计算。

import java.util.Arrays;
import java.util.List;

public class ProductExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4);

        // 使用 reduce 计算乘积
        int product = numbers.stream()
                .reduce(1, (a, b) -> a * b);

        System.out.println("Product: " + product); // 输出 24
    }
}

4. Optional reduce() 的特殊处理

reduce() 方法没有初始值时,返回的是一个 Optional<T>,因为流可能为空。开发者需要显式处理 Optional

示例

import java.util.Arrays;
import java.util.Optional;

public class OptionalReduce {
    public static void main(String[] args) {
        // 空流的情况
        Optional<Integer> result = Arrays.asList().stream()
                .reduce((a, b) -> a + b);

        // 处理 Optional
        System.out.println(result.orElse(0)); // 如果为空,输出 0
    }
}

5. reduce() 的高级用法

5.1 使用 combiner 处理并行流

当使用并行流时,reduce() 的第三个参数 combiner 非常重要,它用于合并多个线程的部分结果。

import java.util.Arrays;
import java.util.List;

public class ParallelReduceExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用并行流和 combiner
        int sum = numbers.parallelStream()
                .reduce(0,
                        Integer::sum, // 累加器
                        Integer::sum  // 组合器
                );

        System.out.println("Sum using parallel stream: " + sum); // 输出 15
    }
}

5.2 统计单词长度

通过 reduce() 计算单词总长度。

import java.util.Arrays;
import java.util.List;

public class WordLengthExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry");

        // 使用 reduce 统计总长度
        int totalLength = words.stream()
                .reduce(0,
                        (length, word) -> length + word.length(),
                        Integer::sum);

        System.out.println("Total length: " + totalLength); // 输出 17
    }
}

6. 小结

  1. 选择适当的初始值:有初始值的 reduce() 更安全,因为它不会返回 Optional
  2. 明确操作的数学意义reduce() 适合处理具有结合律和交换律的操作。
  3. 善用 combiner:在并行流中,combiner 能确保结果正确合并。
  4. 关注性能:对大流使用并行流的 reduce() 可以显著提升效率。

通过 reduce(),我们可以优雅地处理复杂的数据聚合需求,使代码更加简洁高效。

欢迎follow同名gzh: 加瓦点灯,每天推送干货知识,每天进步一点点!@@

本文由mdnice多平台发布

标签:java,Stream,Arrays,reduce,public,util,import,Java8
From: https://www.cnblogs.com/javadd/p/18674557

相关文章

  • Java中的高效集合操作:Stream API实战指南
    Java中的高效集合操作:StreamAPI实战指南1.引言:集合操作的痛点在日常开发中,我们经常需要对集合进行各种操作,比如过滤、映射、排序、聚合等。传统的做法是使用for循环或Iterator,代码冗长且容易出错。比如:List<String>names=newArrayList<>();for(Useruser:users......
  • 深挖 Java8的Stream.flatMap:你不知道的流式操作技巧
    flatMap()是Java8StreamAPI的核心方法之一,主要用于将嵌套结构展开并生成一个新的流。它的强大之处在于能够处理复杂数据结构并将其转换为简单的线性流。以下是flatMap()的常见用法和应用场景:1.将嵌套集合展开为单一流用法处理嵌套的List或Set,将其扁平化为单一流。......
  • Windows 行为测试 删除 FileStream 正在读写文件可以继续读写
    测试结论:使用FileShare带Delete的共享方式打开的FileStream正在对文件进行读写过程中,可以对正在读写的文件进行删除。文件删除之后,不影响已经打开的FileStream的读写。且此时使用File.Exists方法判断文件是否存在,返回的是不存在如果删除之后,再次在外部新建同名文件,则......
  • Java8日期时间类
    1、概述java8在java.time包下重新实现了日期相关类。主要有LocalDate、LocalTime、LocalDateTime。每个类功能明确清晰、类之间协作简单、API定义清晰、功能强大无需借助外部工具类,并且线程安全。2、LocalDate表示没有时区的日期,常用于不需要时间信息的日期操作,即年、月和......
  • 『玩转Streamlit』--查看K线的小工具
    在金融市场分析中,查看不同交易对的K线数据是一项基础且重要的工作。今天,我们就来学习如何使用Streamlit构建一个简单的K线查看小工具,让你能够方便地查看不同交易对在不同时间范围内的K线数据。1.环境准备首先,确保已经安装了必要的库。除了Streamlit用于构建界面,还......
  • 开发指南089-Stream API
        业务处理中会对从数据库返回集合元素进行加工处理,传统方法是使用for循环。平台遵循现代编程理念(回调函数、链式编程)等推荐使用StreamAPI。    第一步:创建Stream       List对象(通常是jpa调用后的实例类的集合),直接调用stream()函数   ......
  • streamlit实现聊天机器人应用,掌握使用Python构建好看web的页面
     第一个可视化的大模型应用。实现一个带有可视化界面的聊天机器人应用,可以将我们之前实现的聊天机器人转化为一个更加直观、用户友好的,我们的第一个可视化的大模型应用。通过使用Streamlit,我们借助st.columns、st.container、st.chat_input和st.chatmessage等streamlitAPl......
  • Streamlit,Streamlit会话及使用指南,将Streamlit部署到云端,通过Streamlit实现聊天机
    Streamlit介绍Streamlit是一个开源的Python库,专为快速创建数据可视化Web应用而设计。它的核心优势在于能够将简单的Python脚本迅速转换成交互式的Web应用,从而使数据科学家和工程师能够以最少的前端开发投入分享他们的数据分析成果。我们本门课程使用Streamlit构建我们的实战项目......
  • Nginx:Stream模块
    什么是Stream模块?Stream模块是Nginx的一个核心模块,专为处理非HTTP协议的流量(TCP和UDP流量)而设计。它可以用来负载均衡和代理TCP或UDP连接,适用于多种应用场景,如:数据库集群(MySQL、PostgreSQL等)邮件服务器(SMTP、IMAP、POP3)游戏服务器VoIP服务自定义协......
  • 『玩转Streamlit』--集成定时任务
    学习了Streamlit了之后,可以尝试给自己的命令行小工具加一个简单的界面。本篇总结了我改造自己的数据采集的工具时的一些经验。1.概要与常规的程序相比,数据采集任务的特点很明显,比如它一般都是I/O密集型程序,涉及大量网络请求或文件读写,耗费的时间比较长;而且往往是按照一定的时......