深入探索 Java Stream

news2025/3/13 11:14:22



引言

在 Java 编程领域,随着数据量的不断增长以及对高效数据处理需求的日益迫切,Java 8 引入的 Stream API 成为了开发者们的得力助手。Stream API 为 Java 集合框架带来了一种全新的、高效且简洁的数据处理方式,极大地提升了代码的可读性与执行效率。它以函数式编程风格为基础,允许开发者以声明式的方式处理数据,将复杂的数据处理逻辑简化为一系列流畅的操作。

一、Java Stream 基础
  1. 定义与概念
    Stream 是 Java 8 中引入的一个接口,它代表一个元素序列,支持顺序和并行的聚合操作。与传统的集合不同,Stream 并不存储元素,而是在运行时通过数据源(如集合、数组等)生成元素序列,并对这些元素进行各种操作。Stream 操作可以分为中间操作和终端操作,中间操作返回一个新的 Stream,允许链式调用多个操作;终端操作则会触发 Stream 的执行,并返回一个最终结果。
  2. 特点
    • 函数式编程风格:Stream API 采用函数式编程思想,开发者通过传递函数来定义对元素的操作,而非使用传统的命令式循环。这种方式避免了可变状态和副作用,使代码更加简洁、易读且线程安全。例如,在使用 Stream 对列表元素进行过滤时,只需传递一个过滤条件的函数,而无需手动编写循环和条件判断。
    • 延迟执行:Stream 操作具有延迟执行的特性。当调用中间操作(如 filtermap 等)时,Stream 并不会立即处理元素,而是将这些操作记录下来,形成一个操作链。直到终端操作(如 collectreduce 等)被调用时,Stream 才会一次性遍历数据源,执行整个操作链,这种特性提高了数据处理的效率,尤其在处理大规模数据时效果显著。
    • 并行处理:Stream API 天然支持并行处理。开发者只需简单地调用 parallelStream() 方法,即可将顺序流转换为并行流,利用多核处理器的优势对数据进行并行处理,大大缩短了数据处理时间。例如,在对一个庞大的数字列表进行复杂计算时,并行流能够显著提升处理速度。
二、Java Stream 常用操作的语法结构及示例
  1. 过滤(filter)
    • 语法结构Stream<T> filter(Predicate<? super T> predicate)
    • 参数说明Predicate 是一个函数式接口,它接受一个元素并返回一个布尔值,表示该元素是否满足条件。
    • 示例代码
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamFilterExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<Integer> evenNumbers = numbers.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println(evenNumbers);
    }
}

在上述代码中,filter(n -> n % 2 == 0) 语句定义了过滤条件,即筛选出能被 2 整除的整数。最终通过 collect(Collectors.toList()) 将符合条件的元素收集到一个新的列表中。
2. 映射(map)
- 语法结构<R> Stream<R> map(Function<? super T,? extends R> mapper)
- 参数说明Function 是一个函数式接口,它接受一个元素并返回一个新的元素。
- 示例代码

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamMapExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry");
        List<Integer> wordLengths = words.stream()
                .map(String::length)
                .collect(Collectors.toList());
        System.out.println(wordLengths);
    }
}

这里使用了方法引用 String::length,它等价于 word -> word.length(),将每个字符串映射为其长度。通过这种方式,我们可以方便地对 Stream 中的元素进行各种转换操作。
3. 排序(sorted)
- 无参语法结构Stream<T> sorted()
- 说明:对元素进行自然排序,要求元素实现 Comparable 接口。
- 带比较器语法结构Stream<T> sorted(Comparator<? super T> comparator)
- 参数说明Comparator 是一个函数式接口,用于定义元素的排序规则。
- 示例代码

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class StreamSortedExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);
        // 自然排序
        List<Integer> naturalSortedNumbers = numbers.stream()
                .sorted()
                .collect(Collectors.toList());
        System.out.println("自然排序: " + naturalSortedNumbers);

        // 降序排序
        List<Integer> reverseSortedNumbers = numbers.stream()
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());
        System.out.println("降序排序: " + reverseSortedNumbers);
    }
}
  1. 归约(reduce)
    • 有初始值语法结构T reduce(T identity, BinaryOperator<T> accumulator)
      • 参数说明identity 是初始值,BinaryOperator 是一个函数式接口,用于对两个元素进行累积操作。
    • 无初始值语法结构Optional<T> reduce(BinaryOperator<T> accumulator)
    • 示例代码
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

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

        // 有初始值的归约
        int sumWithIdentity = numbers.stream()
                .reduce(0, (a, b) -> a + b);
        System.out.println("有初始值的总和: " + sumWithIdentity);

        // 无初始值的归约
        Optional<Integer> sumWithoutIdentity = numbers.stream()
                .reduce((a, b) -> a + b);
        if (sumWithoutIdentity.isPresent()) {
            System.out.println("无初始值的总和: " + sumWithoutIdentity.get());
        }
    }
}
三、Java Stream 的应用场景
  1. 数据处理与分析
    在大数据处理和数据分析场景中,Stream API 发挥着重要作用。例如,在处理海量用户数据时,我们可以使用 Stream 对用户列表进行过滤,筛选出特定年龄段、特定地区的用户;通过映射操作,提取用户的关键信息(如年龄、性别、消费金额等);再利用归约操作进行数据统计,如计算用户的平均消费金额、最大消费金额等。Stream 的并行处理能力使得这些复杂的数据处理任务能够在短时间内完成。
  2. 集合操作优化
    Stream API 为集合操作提供了更加便捷和高效的方式。在对集合进行元素筛选、转换、排序等操作时,使用 Stream 可以避免编写冗长的循环代码,使代码更加简洁明了。例如,在一个电商系统中,对商品列表进行价格过滤、按照销量排序等操作,使用 Stream 可以极大地简化代码逻辑,提高开发效率。
  3. 函数式编程实践
    对于追求函数式编程风格的开发者,Stream API 是实践函数式编程的理想工具。它鼓励开发者将数据处理逻辑分解为一个个独立的函数,通过组合这些函数来实现复杂的功能。这种编程方式使得代码更加模块化、可维护性更强,同时也有助于提高代码的可读性和可扩展性。
四、总结

Java Stream API 为 Java 开发者提供了一种强大、高效且简洁的数据处理方式。通过掌握 Stream 的基础概念、常用操作以及应用场景,开发者能够在日常编程中更加高效地处理数据,提升代码的质量和性能。在大数据时代,Stream API 的优势愈发明显,它不仅能够简化数据处理逻辑,还能充分利用多核处理器的性能,为开发者带来更加流畅和高效的编程体验。

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

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

相关文章

MCP-代码解读TypeScript版本

MCP-代码解读TypeScript版本 文章目录 MCP-代码解读TypeScript版本1-参考网址2-TypeScript代码3-代码解读1-[非重点]定义函数2-[非重点]定义工具说明3-[重点]运行MCP服务 1-参考网址 B站视频参考 2-TypeScript代码 import { McpServer } from "modelcontextprotocol/sd…

写了一个二叉树构造函数和画图函数,方便debug

代码 class TreeNode(object):def __init__(self, val, leftNone, rightNone):self.val valself.left leftself.right rightdef construct_tree(nodes):if not nodes:return Noneroot TreeNode(nodes[0])queue [root]index 1while index < len(nodes):node queue.p…

docker 小记

一、卸载 查看当前版本 docker -v2. 如果有&#xff0c;先停止docker systemctl stop docker如果是yum安装&#xff0c;卸载方式为 #已防版本冲突&#xff0c;直接卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-lat…

G-Star 公益行起航,挥动开源技术点亮公益!

公益组织&#xff0c;一直是社会温暖的传递者&#xff0c;但在数字化浪潮中&#xff0c;也面临着诸多比大众想象中复杂的挑战&#xff1a;项目管理如何更高效&#xff1f;志愿者管理又该如何创新&#xff1f;宣传推广怎么才能更有影响力&#xff1f;内部管理和技术支持又该如何…

k9s入门及实战

概述 k9s&#xff0c;GitHub&#xff0c;是用于管理k8s集群的CLI&#xff0c;提供一个终端UI来与k8s集群进行交互。通过封装kubectl功能&#xff0c;k9s会以特定时间间隔监控k8s的变化&#xff0c;默认为2秒&#xff0c;并提供后续命令来与k8s资源进行交互&#xff0c;k9s可让…

redis增加ip白名单

Redis增加IP白名单 随着互联网的快速发展&#xff0c;网络安全问题也日益凸显。为了保护服务器安全&#xff0c;我们常常需要对访问服务器的IP地址进行限制。而Redis作为一种高性能的缓存数据库&#xff0c;可以用来实现IP白名单功能。本文将介绍如何使用Redis来增加IP白名单&…

git commit messege 模板设置 (规范化管理git)

配置方法 git config --global core.editor vim &#xff08;设置 Git 的默认编辑器为 Vim&#xff09;在用户根目录下&#xff08;~&#xff09;&#xff0c;创建一个.git_commit_msg文件&#xff0c;然后把下面的内容拷贝到文件中并保存。 [version][模块][类型]{解决xxx问题…

Franka机器人ROS 2 发布:赋能机器人研究和行业应用

Franka机器人 ROS 2 发布&#xff1a;赋能机器人研究和行业应用 Franka ROS 2 发布&#xff1a;赋能机器人研究和行业应用 由zlem Odeh 于Franka Robotics 发布 在机器人操作系统 (ROS) 等技术和生态系统的推动下&#xff0c;机器人世界正以前所未有的速度发展。ROS 2 是广受…

docker部署jenkins,安装使用一条龙教程

Jenkins k8s 实现CI/CD 一、简介 1. JenKins是什么? Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。 2. 什么是CI / CD…

短视频下载去水印,用什么工具好?

去除视频和图片水印是许多用户的需求&#xff0c;尤其是在分享或保存内容时。以下是6款超好用的工具&#xff0c;帮助你轻松去除水印&#xff0c;享受纯净的视觉体验&#xff1a; 1. 易下载去水印小程序 特点&#xff1a; 操作简单&#xff0c;支持抖音、快手、小红书、哔哩哔哩…

推理大模型时代,TextIn ParseX助力出版业知识资产重构

在大语言模型&#xff08;LLM&#xff09;与推理能力快速进化的技术浪潮下&#xff0c;出版机构沉淀数十年的非结构化数据资产&#xff0c;包括书籍、期刊、手稿及历史档案&#xff0c;正在焕发新的机遇。基于文档解析、NLP与大模型的推理生成能力&#xff0c;我们在图书馆层层…

Redis 2025/3/9

Redis主从集群 搭建主从集群 Redis并发能力非常强&#xff0c;单节点能够达到数万的并发。 不过对一些用户规模大&#xff0c;并发量比较高的应用来讲&#xff0c;数万并发不太够。这时候就用到redis的集群了。因为Redis中的数据通常读多写少&#xff0c;所以最常用的集群方…

2min搞定~Mac Pro 编译安装 Nginx 1.8.1

2min搞定&#xff5e;Mac Pro 编译安装 Nginx 1.8.1 一安装流程简述1、编译源码前&#xff0c;获取要依赖的源码包2、进行编译、安装nginx3、启动 二、实战部分&#xff1a;测试demo1、nginx.conf改动2、代码改动3、访问 一安装流程简述 阿哟啊哟老铁&#xff0c;别嫌我啰嗦奥…

要在Unreal Engine 5(UE5)中实现角色打击怪物并让怪物做出受击反应,

UE5系列文章目录 文章目录 UE5系列文章目录前言一、实现思路二、最终效果 前言 ue5角色受击没有播放受击动画&#xff0c;主角达到怪物身上没有反应 一、实现思路 要在Unreal Engine 5&#xff08;UE5&#xff09;中实现角色打击怪物并让怪物做出受击反应&#xff0c;你需要…

C++蓝桥杯基础篇(十一)

片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来学习C蓝桥杯基础篇&#xff08;十一&#xff09;&#xff0c;学习类&#xff0c;结构体&#xff0c;指针相关知识&#xff0c;准备好了吗&#xff1f;咱们开始咯~ 一、类与结构体 类的定义&#xff1a;在C中&#x…

Leetcode 698-划分为k个相等的子集

给定一个整数数组 nums 和一个正整数 k&#xff0c;找出是否有可能把这个数组分成 k 个非空子集&#xff0c;其总和都相等。 示例 1&#xff1a; 输入&#xff1a; nums [4, 3, 2, 3, 5, 2, 1], k 4 输出&#xff1a; True 说明&#xff1a; 有可能将其分成 4 个子集&#…

Word 小黑第2套

对应大猫42 Word1 从文件中导入新样式 样式组 -管理样式 -导入导出 -关闭Normal文件 -打开文件 -修改文件 -选中所需 -复制 调整字符宽度 调整字符间距 -字体组 加宽 适当修改磅值 文字效果通过文字组修改 另起一页&#xff0c;分隔符&#xff08;布局 -分隔符 -分节符 -下一…

ctfshow做题笔记—栈溢出—pwn69~pwn72

目录 前言 一、pwn69(可以尝试用ORW读flag flag文件位置为/ctfshow_flag) 二、pwn70(可以开始你的个人秀了 flag文件位置为/flag) 三、pwn71(32位的ret2syscall) 四、pwn72 前言 学了一些新的东西&#xff0c;pwn69的文档忘保存了&#xff08;悲&#xff09;&#xff0c…

同盾v2 2025版 blackbox , wasm加解密,逆向协议算法生成,小盾安全

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; # 欢迎交流 wjxch1004

c++领域展开第十六幕——STL(vector容器的了解以及模拟实现、迭代器失效问题)超详细!!!!

文章目录 前言一、vector的介绍和使用1.1 vector的介绍1.2 vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector的空间增长问题1.2.4 vector的增删改查 二、vector在 oj 中的使用只出现一次的数删除有序数组中的重复项杨辉三角 总结 前言 在c专栏的上一篇…