Java 8 的流(Stream API)简介

news2025/4/11 9:28:23

Java 8 引入的 Stream API 是一个强大的工具,用于处理集合(如 List、Set)中的元素。它支持各种操作,包括过滤、排序、映射等,并且能够以声明式的方式表达复杂的查询操作。流操作可以是中间操作(返回流以便进一步处理)或终端操作(产生结果或副作用)。此外,Stream API 还支持并行执行,从而利用多核处理器的优势。

Stream 的基本概念


  • 任何提供数据的集合(如 ListSet、数组等)均可作为流的来源。

  • 中间操作
    返回新流对象,支持链式调用,惰性求值。常见操作包括:

    • filter(筛选)
    • map(映射)
    • sorted(排序)
    • distinct(去重)
    • limit(限制数量)
    • skip(跳过元素)
    • flatMap(扁平化映射)
    • peek(调试查看)
  • 终端操作
    触发流处理并生成结果,执行后流被消耗。常见操作包括:

    • forEach(遍历)
    • collect(收集到集合)
    • reduce(聚合)
    • count(统计数量)
    • findFirst/findAny(查找元素)
    • anyMatch/allMatch/noneMatch(匹配验证)

创建 Stream 的方式

  1. 从集合创建

    List<String> list = Arrays.asList("apple", "banana", "pear");
    Stream<String> stream = list.stream();
  2. 从数组创建

    String[] arr = {"apple", "banana", "pear"};
    Stream<String> stream = Arrays.stream(arr);
  3. 生成无限流

    // 迭代生成(0, 1, 2, ...)
    Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);
    
    // 随机生成
    Stream<Double> randomStream = Stream.generate(Math::random);

中间操作详解

1. 筛选与切片

  • filter:按条件筛选元素

    List<String> filtered = list.stream()
        .filter(s -> s.length() > 3)
        .collect(Collectors.toList());
  • distinct:去重(需重写 equals 和 hashCode

    List<Integer> distinctList = Arrays.asList(1, 2, 2, 3)
        .stream()
        .distinct()
        .collect(Collectors.toList()); // [1, 2, 3]
  • limit:截取前 N 个元素

    List<String> firstTwo = list.stream()
        .limit(2)
        .collect(Collectors.toList());
  • skip:跳过前 N 个元素

    List<String> skipped = list.stream()
        .skip(1)
        .collect(Collectors.toList());

2. 映射与扁平化

  • map:元素类型转换

    List<String> upperCase = list.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());
  • flatMap:扁平化嵌套集合

    List<List<Integer>> nestedList = Arrays.asList(
        Arrays.asList(1, 2),
        Arrays.asList(3, 4)
    );
    List<Integer> flatList = nestedList.stream()
        .flatMap(List::stream)
        .collect(Collectors.toList()); // [1, 2, 3, 4]

3. 排序

  • 自然排序

    List<String> sortedList = list.stream()
        .sorted()
        .collect(Collectors.toList());
  • 自定义排序

    List<Employee> sortedEmployees = employees.stream()
        .sorted((e1, e2) -> e2.getAge() - e1.getAge())
        .collect(Collectors.toList());

4. 调试查看

  • peek:遍历元素时执行操作(如打印)
    list.stream()
        .peek(System.out::println)
        .collect(Collectors.toList());

终端操作详解

1. 收集结果

  • 收集到集合

    List<String> listResult = Stream.of("a", "b", "c")
        .collect(Collectors.toList());
    
    Set<String> setResult = Stream.of("apple", "banana", "pear")
        .collect(Collectors.toSet());
  • 分组与分区

    Map<Integer, List<String>> grouped = list.stream()
        .collect(Collectors.groupingBy(s -> s.length()));

2. 聚合操作

  • reduce 求和

    int sum = numbers.stream()
        .reduce(0, (a, b) -> a + b);
  • 拼接字符串

    String joined = Stream.of("a", "b", "c")
        .reduce("", (a, b) -> a + b); // "abc"
  • 无初始值的聚合

    Optional<Integer> max = numbers.stream()
        .reduce(Integer::max);

3. 查找与匹配

  • findFirst:获取第一个元素

    Optional<String> first = list.stream()
        .filter(s -> s.startsWith("a"))
        .findFirst();
  • findAny:获取任意元素(并行流中可能乱序)

    Optional<String> any = list.parallelStream()
        .findAny();
  • max/min:获取极值

    Optional<Integer> maxNumber = numbers.stream()
        .max(Integer::compare);

4. 匹配验证

  • anyMatch:至少一个元素满足条件

    boolean hasEven = numbers.stream()
        .anyMatch(n -> n % 2 == 0);
  • allMatch:所有元素满足条件

    boolean allEven = numbers.stream()
        .allMatch(n -> n % 2 == 0);
  • noneMatch:无元素满足条件

    boolean noEven = numbers.stream()
        .noneMatch(n -> n % 2 == 0);

5. 统计与转换

  • count:统计元素数量

    long count = list.stream()
        .filter(s -> s.length() > 3)
        .count();
  • toArray:转换为数组

    String[] array = list.stream()
        .toArray(String[]::new);
  • 数值统计

    IntSummaryStatistics stats = numbers.stream()
        .mapToInt(Integer::intValue)
        .summaryStatistics();
    System.out.println(stats.getAverage()); // 平均值

6. 遍历操作

  • forEach:执行副作用操作
    list.stream()
        .forEach(System.out::println);

并行流(Parallel Stream)

  • 启用并行流

    List<String> list = Arrays.asList("apple", "banana", "pear");
    list.parallelStream().forEach(System.out::println);
  • 注意事项

    • 并行流可能提高大数据集处理性能。
    • 需确保线程安全性(如避免共享状态修改)。
    • 并行排序(sorted())可能不稳定,需谨慎使用。

注意事项

  1. 中间操作顺序
    逻辑顺序需合理(如先 filter 再 map)。

  2. 对象去重
    使用 distinct() 时需重写 hashCode() 和 equals()

  3. 流复用问题
    终端操作后流被消耗,需重新创建流:

    Stream<String> stream = list.stream();
    stream.forEach(System.out::println); // 首次使用
    stream.forEach(System.out::println); // 报错!流已关闭
  4. 安全获取值
    使用 Optional 的 orElse()orElseGet() 或 orElseThrow() 避免空指针。

总结

Java 8 Stream API 通过声明式编程简化了集合操作,支持链式调用和并行处理。合理使用中间操作(如 filtermap)和终端操作(如 collectreduce),可高效完成数据聚合、过滤及验证。结合并行流可显著提升大数据集处理性能,但需注意线程安全性和操作顺序。

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

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

相关文章

element-plus中,表单校验的使用

目录 一.案例1&#xff1a;给下面的表单添加校验 1.目的要求 2.步骤 ①给需要校验的el-form-item项&#xff0c;添加prop属性 ②定义一个表单校验对象&#xff0c;里面存放了每一个prop的检验规则 ③给el-form组件&#xff0c;添加:rules属性 ④给el-form组件&#xff0…

PyTorch复现线性模型

【前言】 本专题为PyTorch专栏。从本专题开始&#xff0c;我将通过使用PyTorch编写基础神经网络&#xff0c;带领大家学习PyTorch。并顺便带领大家复习以下深度学习的知识。希望大家通过本专栏学习&#xff0c;更进一步了解人更智能这个领域。 材料来源&#xff1a;2.线性模型_…

Kafka+Zookeeper从docker部署到spring boot使用完整教程

文章目录 一、Kafka1.Kafka核心介绍&#xff1a;​核心架构​核心特性​典型应用 2.Kafka对 ZooKeeper 的依赖&#xff1a;3.去 ZooKeeper 的演进之路&#xff1a;注&#xff1a;&#xff08;本文采用ZooKeeper3.8 Kafka2.8.1&#xff09; 二、Zookeeper1.核心架构与特性2.典型…

RK3568驱动 SPI主/从 配置

一、SPI 控制器基础配置(先说主的配置&#xff0c;后面说从的配置) RK3568 集成高性能 SPI 控制器&#xff0c;支持主从双模式&#xff0c;最高传输速率 50MHz。设备树配置文件路径通常为K3568/rk356x_linux_release_v1.3.1_20221120/kernel/arch/arm64/boot/dts/rockchip。 …

【全队项目】智能学术海报生成系统PosterGenius--风格个性化调整

​ &#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#x1f3c0;大模型实战训练营 ​&#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 1.前言 PosterGenius致力于开发一套依托DeepSeek…

【系统移植】(六)第三方驱动移植

【系统移植】&#xff08;六&#xff09;第三方驱动移植 文章目录 【系统移植】&#xff08;六&#xff09;第三方驱动移植1.编译驱动进内核方法一&#xff1a;编译makefile方法二&#xff1a;编译kconfig方法三&#xff1a;编译成模块 2.字符设备框架 编译驱动进内核a. 选择驱…

STM32实现一个简单电灯

新建工程的步骤 建立工程文件夹&#xff0c;Keil中新建工程&#xff0c;选择型号工程文件夹里建立Start、Library、User等文件夹&#xff0c;复制固件库里面的文件到工程文件夹工程里对应建立Start、Library、User等同名称的分组&#xff0c;然后将文件夹内的文件添加到工程分组…

【shiro】shiro反序列化漏洞综合利用工具v2.2(下载、安装、使用)

1 工具下载 shiro反序列化漏洞综合利用工具v2.2下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1kvQEMrMP-PZ4K1eGwAP0_Q?pwdzbgp 提取码&#xff1a;zbgp其他工具下载&#xff1a; 除了该工具之外&#xff0c;github上还有其他大佬贡献的各种工具&#xff0c;有…

vue进度条组件

<div class"global-mask" v-if"isProgress"><div class"contentBox"><div class"progresstitie">数据加载中请稍后</div><el-progress class"progressStyle" :color"customColor" tex…

CSRF跨站请求伪造——入门篇【DVWA靶场low级别writeup】

CSRF跨站请求伪造——入门篇 0. 前言1. 什么是CSRF2. 一次完整的CSRF攻击 0. 前言 本文将带你实现一次完整的CSRF攻击&#xff0c;内容较为基础。需要你掌握的基础知识有&#xff1a; 了解cookie&#xff1b;已经安装了DVWA的靶场环境&#xff08;本地的或云的&#xff09;&am…

Qt基础:主界面窗口类QMainWindow

QMainWindow 1. QMainWindow1.1 菜单栏添加菜单项菜单项信号槽 1.2 工具栏添加工具按钮工具栏的属性设置 1.3 状态栏1.4 停靠窗口&#xff08;Dock widget&#xff09; 1. QMainWindow QMainWindow是标准基础窗口中结构最复杂的窗口, 其组成如下: 提供了菜单栏, 工具栏, 状态…

32f4,usart2fifo,2025

usart2fifo.h #ifndef __USART2FIFO_H #define __USART2FIFO_H#include "stdio.h" #include "stm32f4xx_conf.h" #include "sys.h" #include "fifo_usart2.h"//extern u8 RXD2_TimeOut;//超时检测//extern u8 Timer6_1ms_flag;exte…

激光模拟单粒子效应试验如何验证CANFD芯片的辐照阈值?

在现代航天电子系统中&#xff0c;CANFD&#xff08;Controller Area Network with Flexible Data-rate&#xff09;芯片作为关键的通信接口元件&#xff0c;其可靠性与抗辐射性能直接关系到整个系统的稳定运行。由于宇宙空间中存在的高能粒子辐射&#xff0c;芯片可能遭受单粒…

从零构建大语言模型全栈开发指南:第五部分:行业应用与前沿探索-5.2.1模型偏见与安全对齐(Red Teaming实践)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 大语言模型全栈开发指南:伦理与未来趋势 - 第五部分:行业应用与前沿探索5.2.1 模型偏见与安全对齐(Red Teaming实践)一、模型偏见的来源与影响1. 偏见的定义与分类2. 偏见的实际影响案例二、安全对齐…

Docker安装开源项目x-ui详细图文教程

本章教程,主要介绍如何使用Docker部署开源项目x-ui 详细教程。 一、拉取镜像 docker pull enwaiax/x-ui:latest二、运行容器 mkdir x-ui && cd x-ui docker run -itd --network=host \-v $PWD<

检索增强生成(RAG) 优化策略

检索增强生成(RAG) 优化策略篇 一、RAG基础功能篇 1.1 RAG 工作流程 二、RAG 各模块有哪些优化策略&#xff1f;三、RAG 架构优化有哪些优化策略&#xff1f; 3.1 如何利用 知识图谱&#xff08;KG&#xff09;进行上下文增强&#xff1f; 3.1.1 典型RAG架构中&#xff0c;向…

零基础玩转树莓派5!从系统安装到使用VNC远程控制树莓派桌面实战

文章目录 前言1.什么是Appsmith2.Docker部署3.Appsmith简单使用4.安装cpolar内网穿透5. 配置公网地址6. 配置固定公网地址总结 前言 你是否曾因公司内部工具的开发周期长、成本高昂而头疼不已&#xff1f;或是突然灵感爆棚想给团队来点新玩意儿&#xff0c;却苦于没有专业的编…

【MyBatis】深入解析 MyBatis:关于注解和 XML 的 MyBatis 开发方案下字段名不一致的的查询映射解决方案

注解查询映射 我们再来调用下面的 selectAll() 这个接口&#xff0c;执行的 SQL 是 select* from user_info&#xff0c;表示全列查询&#xff1a; 运行测试类对应方法&#xff0c;在日志中可以看到&#xff0c;字段名一致&#xff0c;Mybatis 就成功从数据库对应的字段中拿到…

图像退化对目标检测的影响 !!

文章目录 引言 1、理解图像退化 2、目标检测中的挑战 3、应对退化的自适应方法 4、新兴技术与研究方向 5、未来展望 6、代码 7、结论 引言 在计算机视觉领域&#xff0c;目标检测是一项关键任务&#xff0c;它使计算机能够识别和定位数字图像中的物体。这项技术支撑着从自动驾…

《AI大模型应知应会100篇》第57篇:LlamaIndex使用指南:构建高效知识库

第57篇&#xff1a;LlamaIndex使用指南&#xff1a;构建高效知识库 摘要 在大语言模型&#xff08;LLM&#xff09;驱动的智能应用中&#xff0c;如何高效地管理和利用海量知识数据是开发者面临的核心挑战之一。LlamaIndex&#xff08;原 GPT Index&#xff09; 是一个专为构建…