java基础 流(Stream)

news2025/4/18 3:40:22

Stream

  • Stream 的核心概念
    • 核心特点
  • Stream 的操作分类
    • 中间操作(Intermediate Operations)
    • 终止操作(Terminal Operations)
  • Stream 的流分类
    • 顺序流(Sequential Stream)
    • 并行流(Parallel Stream)
      • 并行流的注意事项
      • 并行流的底层机制
    • 顺序流 vs 并行流的对比
    • 顺序流和并行流的示例代码
    • 顺序流并行流总结

Stream 的核心概念

Java 8 引入的 Stream API 是一种基于函数式编程的数据处理抽象,允许以声明式方式操作集合(如过滤、映射、排序等)。Stream 不是数据结构,而是对数据源(集合、数组、I/O 等)的高效计算工具

核心特点

  • 链式调用:通过多个操作(中间操作 + 终止操作)串联处理数据
  • 惰性求值:中间操作(如 filter, map)不会立即执行,直到遇到终止操作(如 collect, forEach)
  • 不可复用:一个 Stream 只能被消费一次,再次使用会抛出 IllegalStateException
  • 并行处理:可通过简单方法(parallel())实现多线程并行计算

Stream 的操作分类

中间操作(Intermediate Operations)

返回新的 Stream,支持链式调用,常见方法示例:filter(), map(), sorted(), distinct()。

        List<Integer> list = Arrays.asList(1, 2, 2,3);
        list.stream().distinct().forEach(System.out::println);//用于去除流中的重复元素。
        list.stream().map(x -> x * x).forEach(System.out::println);//用于对流中的每个元素应用一个函数,并返回一个新的流
        list.stream().filter(v->v==3).forEach(System.out::println);//用于对流中的元素进行筛选,只保留满足条件的元素
        list.stream().flatMap(s -> s.toString().chars().boxed()).forEach(System.out::println);//用于将流中的每个元素转换为另一个流,然后将这些流连接成一个流
        list.stream().limit(2).forEach(System.out::println);//用于限制流中元素的数量
        list.stream().skip(2).forEach(System.out::println);//用于跳过流中前n个元素
        list.stream().sorted().forEach(System.out::println);//用于对流中的元素进行排序

支持链式调用

        list.stream().distinct()
        .filter(v->v==3)
        .sorted()
        .map(x -> x * x).forEach(System.out::println);

但是注意,流中间操作的方法返回的结果依然是流,但是上面为了显示这些方法使用的样例里面
forEach(System.out::println)这个是终止操作方法,也就是在forEach方法之前的返回的是流,在使用forEach方法之后返回的又将流转换非 Stream 结果

终止操作(Terminal Operations)

触发实际计算,返回非 Stream 结果(如集合、数值、void),常见方法示示例:collect(), forEach(), reduce(), count()

        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.stream().forEach(System.out::println);//对流中的每个元素执行指定的操作 这里是打印
        names.stream() .map(String::toUpperCase).collect(Collectors.toList()).forEach(System.out::println);//将流中的元素收集到一个容器中
        System.out.println(names.stream().allMatch(s -> s.contains("s")));//allMatch 检查是否匹配所有元素
        System.out.println(names.stream().anyMatch(s -> s.contains("a")));//anyMatch 检查是否至少匹配一个元素
        System.out.println(names.stream().noneMatch(s -> s.contains("x")));//noneMatch:检查是否没有匹配所有元素
        System.out.println(names.stream().findFirst());//findFirst:返回当前流中的第一个元素
        System.out.println(names.stream().findAny());//findAny:返回当前流中的任意元素
        System.out.println(names.stream().count());//count:返回流中元素总数
        System.out.println(names.stream().max(Comparator.comparingInt(s->s.length())));//max:返回流中最大值
        System.out.println(names.stream().min(Comparator.comparingInt(s->s.length())));//min:最小值

Stream 的流分类

顺序流(Sequential Stream)

默认模式:所有操作在单线程中按顺序执行

List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.stream(); // 顺序流

适用场景:
数据量较小,或操作本身简单。
需要保证操作顺序(如 sorted() 依赖前序操作结果)。

并行流(Parallel Stream)

Stream<Integer> parallelStream = list.parallelStream(); // 并行流Stream<Integer> parallelStream = list.stream().parallel(); // 转换为并行流

适用场景:
数据量较大,且任务可独立拆分(无共享状态或顺序依赖)。
操作耗时(如复杂计算、I/O 等待)。

并行流的注意事项

1.线程安全问题
确保操作中使用的 Lambda 表达式或函数是线程安全的(避免共享可变状态)。
示例错误:

List<Integer> result = new ArrayList<>();
list.parallelStream().forEach(result::add); // 并发修改 ArrayList 导致数据错误

应使用线程安全的收集器(如 Collectors.toList()):

List<Integer> result = list.parallelStream().collect(Collectors.toList());

2.性能未必更好
并行流需额外开销(任务拆分、线程调度),对小数据量可能更慢。
测试性能:通过基准测试(如 JMH) 验证是否适合并行

3.顺序依赖操作
如 limit()、findFirst() 在并行流中可能性能更差,需改用无序流

list.parallelStream().unordered().limit(10); // 提升性能

ORDERED是Spliterator的特征值, 特征要求并行流保持元素顺序(如 List),改成unordered就是改成序列流,除此之外

并行流的底层机制

1.Spliterator
并行流通过 Spliterator(可拆分迭代器) 将数据源拆分为多个子任务,是 Stream API 并行处理的底层实现

List<String> list = Arrays.asList("Java", "Python", "C++", "Go");

// 使用并行流处理
list.parallelStream() // 将数据源拆分为多个子任务
    .map(String::toUpperCase)
    .forEach(System.out::println);

// 输出(顺序不确定,因为并行处理):
// PYTHON
// JAVA
// GO
// C++

2.ForkJoinPool
并行流默认使用公共的 ForkJoinPool(线程数 = CPU 核心数)。通过系统属性修改默认线程池大小

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "8");

3.自定义线程池(避免影响全局)

ForkJoinPool customPool = new ForkJoinPool(4);
customPool.submit(() -> list.parallelStream().forEach(...)).get();

顺序流 vs 并行流的对比

特性顺序流并行流
线程模型单线程多线程(ForkJoinPool 默认线程池)
性能优势简单任务、小数据量大数据量、可并行化的复杂任务
开销高(线程切换、任务拆分/合并)
顺序保证严格按顺序处理不保证顺序(除非使用有序操作)
数据源要求无特殊要求数据源需可拆分(如 ArrayList

顺序流和并行流的示例代码

顺序流处理

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filtered = names.stream()
        .filter(name -> name.length() > 3)
        .map(String::toUpperCase)
        .collect(Collectors.toList()); // [ALICE, CHARLIE]

并行流处理

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.parallelStream()//通过底层Spliterator拆分为多个子任务
        .filter(n -> n % 2 == 0)
        .mapToInt(n -> n * 2)
        .sum(); // (2+4+6+8+10)*2 = 60

顺序流并行流总结

顺序流:简单、低开销,适合小数据量或顺序敏感操作。
并行流:通过多线程加速处理,适合大数据量和可并行化任务,但需注意线程安全和性能开销。

选择策略:
优先使用顺序流,仅在必要时(且验证有效)切换为并行流。
避免在并行流中操作共享可变状态。

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

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

相关文章

无需libpacp库,BPF指令高效捕获指定数据包

【环境】无libpacp库的Linux服务器 【要求】高效率读取数据包&#xff0c;并过滤指定端口和ip 目前遇到两个问题 一是手写BPF&#xff0c;难以兼容&#xff0c;有些无法正常过滤二是性能消耗问题&#xff0c;尽可能控制到1% 大方向&#xff1a;过滤数据包要在内核层处理&…

react实现上传图片到阿里云OSS以及问题解决(保姆级)

一、优势 提高上传速度&#xff1a;前端直传利用了浏览器与 OSS 之间的直接连接&#xff0c;能够充分利用用户的网络带宽。相比之下&#xff0c;后端传递文件时&#xff0c;文件需要经过后端服务器的中转&#xff0c;可能会受到后端服务器网络环境和处理能力的限制&#xff0c;…

Python 字典和集合(常见的映射方法)

本章内容的大纲如下&#xff1a; 常见的字典方法 如何处理查找不到的键 标准库中 dict 类型的变种set 和 frozenset 类型 散列表的工作原理 散列表带来的潜在影响&#xff08;什么样的数据类型可作为键、不可预知的 顺序&#xff0c;等等&#xff09; 常见的映射方法 映射类型…

Matlab轴承故障信号仿真与故障分析

1.摘要 本文介绍了一个基于Matlab的轴承故障信号仿真与分析程序&#xff0c;旨在模拟和分析轴承内圈故障信号的特征。程序首先通过生成故障信号、共振信号和调制信号&#xff0c;添加噪声和离散化处理&#xff0c;构建模拟的振动信号&#xff0c;并保存相关数据。通过快速傅里…

Linux 进程 | 概念 / 特征 / 状态 / 优先级 / 空间

注&#xff1a; 本文为 “Linux 进程” 相关文章合辑。 未整理去重。 Linux 进程概念&#xff08;精讲&#xff09; A little strawberry 于 2021-10-15 10:23:55 发布 基本概念 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等。 内核观点&#xff…

重回全面发展亲自操刀

项目场景&#xff1a; 今年工作变动&#xff0c;优化后在一家做国有项目的私人公司安顿下来了。公司环境不如以前&#xff0c;但是好在瑞欣依然可以每天方便的买到。人文氛围挺好&#xff0c;就是工时感觉有点紧&#xff0c;可能长期从事产品迭代开发&#xff0c;一下子转变做项…

3D珠宝渲染用什么软件比较好?渲染100邀请码1a12

印度珠宝商 Mohar Fine Jewels 和英国宝石商 Gemfields 在今年推出了合作珠宝系列——「Emeralds in Full Bloom」&#xff0c;它的灵感源自花草绽放的春季田野&#xff0c;共有 39 件作品&#xff0c;下面这个以植物为主题的开口手镯就是其中一件。 在数字时代&#xff0c;像这…

【数据结构】邻接矩阵完全指南:原理、实现与稠密图优化技巧​

邻接矩阵 导读一、图的存储结构1.1 分类 二、邻接矩阵法2.1 邻接矩阵2.2 邻接矩阵存储网 三、邻接矩阵的存储结构四、算法评价4.1 时间复杂度4.2 空间复杂度 五、邻接矩阵的特点5.1 特点1解析5.2 特点2解析5.3 特点3解析5.4 特点4解析5.5 特点5解析5.6 特点6解析 结语 导读 大…

【嵌入式-stm32电位器控制以及旋转编码器控制LED亮暗】

嵌入式-stm32电位器控制LED亮暗 任务1代码1Key.cKey.hTimer.cTimer.hPWM.cPWM.hmain.c 实验现象1任务2代码2Key.cKey.hmain.c 实验现象2问题与解决总结 源码框架取自江协科技&#xff0c;在此基础上做扩展开发。 任务1 本文主要介绍利用stm32f103C8T6实现电位器控制PWM的占空比…

Uniapp 集成极光推送(JPush)完整指南

文章目录 前言一、准备工作1. 注册极光开发者账号2. 创建应用3. Uniapp项目准备 二、集成极光推送插件方法一&#xff1a;使用UniPush&#xff08;推荐&#xff09;方法二&#xff1a;手动集成极光推送SDK 三、配置原生平台参数四、核心功能实现1. 获取RegistrationID2. 设置别…

2025年常见渗透测试面试题-sql(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 SQLi 一、发现test.jsp?cid150 注入点的5种WebShell获取思路 1. 文件写入攻击 2. 日志文件劫持 3.…

【RabbitMQ】队列模型

1.概述 RabbitMQ作为消息队列&#xff0c;有6种队列模型&#xff0c;分别在不同的场景进行使用&#xff0c;分别是Hello World&#xff0c;Work queues&#xff0c;Publish/Subscribe&#xff0c;Routing&#xff0c;Topics&#xff0c;RPC。 下面就分别对几个模型进行讲述。…

StarRocks 助力首汽约车精细化运营

作者&#xff1a;任智红&#xff0c;首汽约车大数据负责人 更多交流&#xff0c;联系我们&#xff1a;https://wx.focussend.com/weComLink/mobileQrCodeLink/334%201%202/ffbe5 导读&#xff1a; 本文整理自首汽约车大数据负责人任智红在 StarRocks 年度峰会上的演讲&#xf…

痉挛性斜颈康复助力:饮食调养指南

痉挛性斜颈患者除了积极治疗&#xff0c;合理饮食也能辅助缓解症状&#xff0c;提升生活质量。其健康饮食可从以下方面着手&#xff1a; 高蛋白质食物助力肌肉修复 痉挛性斜颈会导致颈部肌肉异常收缩&#xff0c;消耗较多能量&#xff0c;蛋白质有助于肌肉的修复与维持。日常可…

mysql镜像创建docker容器,及其可能遇到的问题

前提&#xff0c;已经弄好基本的docker服务了。 一、基本流程 1、目录准备 我自己的资料喜欢放在 /data 目录下&#xff0c;所以老规矩&#xff1a; 先进入 /data 目录&#xff1a; cd /data 创建 mysql 目录并进入&#xff1a; mkdir mysql cd mysql 2、镜像查找 docke…

JavaEE——线程的状态

目录 前言1. NEW2. TERMINATED3. RUNNABLE4. 三种阻塞状态总结 前言 本篇文章来讲解线程的几种状态。在Java中&#xff0c;线程的状态是一个枚举类型&#xff0c;Thread.State。其中一共分为了六个状态。分别为&#xff1a;NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING, TERMI…

RuntimeError: Error(s) in loading state_dict for ChartParser

一 bug错误 最近使用千问大模型有一个bug&#xff0c;报错信息如下 raise RuntimeError(Error(s) in loading state_dict for {}:\n\t{}.format( RuntimeError: Error(s) in loading state_dict for ChartParser:Unexpected key(s) in state_dict: "pretrained_model.em…

2025 年安徽交安安全员考试:利用记忆宫殿强化记忆​

安徽考生在面对交安安全员考试繁杂的知识点时&#xff0c;记忆宫殿是强大的记忆工具。选择一个熟悉且空间结构清晰的场所作为记忆宫殿&#xff0c;如自己居住的房屋。将房屋的不同区域&#xff0c;如客厅、卧室、厨房等&#xff0c;分别对应不同知识板块&#xff0c;像客厅对应…

安全编码课程 实验6 整数安全

实验项目 实现安全计数器&#xff1a;实现 Counter 结构&#xff0c;确保计数范围为 0~100。 实验要求&#xff1a; 1、使用 struct 封装计数值value&#xff1b; 2、计数器初值为 0&#xff1b; 3、increment() 方法增加计数&#xff0c;但不能超过 100&#xff1b; 4、decrem…

解决上传PDF、视频、音频等格式文件到FTP站点时报错“将文件复制到FTP服务器时发生错误。请检查是否有权限将文件放到该服务器上”问题

一、问题描述 可以将文本文件(.txt格式),图像文件(.jpg、.png等格式)上传到我们的FTP服务器上;但是上传一些PDF文件、视频等文件时就会报错“ 将文件复制到FTP服务器时发生错误。请检查是否有权限将文件放到该服务器上。 详细信息: 200 Type set to l. 227 Entering Pas…