Java Stream API 详解
Java Stream API 详解
1. 什么是 Stream API?
Stream API 是 Java 8 引入的一种用于处理集合(如数组、列表)的强大工具。它提供了一种声明性方式处理数据,可以简化代码并提高可读性。Stream 不是数据结构,它只是一种从支持的数据源(如集合、数组等)中提取的元素序列。
组成部分:
- 数据源:任何可以提供数据的地方,例如集合、数组等。
- 操作链:一系列中间和终端操作用于处理数据。
- 最终结果:经过流操作的结果,可能是一个值、一个集合、或根本不返回结果(如打印)。
2. Stream API 的特性
-
声明性:通过函数式编程风格处理数据,而不是使用传统的循环等命令式编程。
例子:不用写 for 循环去遍历集合,而是使用
stream().forEach()来执行操作。 -
惰性求值:Stream 的中间操作是惰性求值的,只有在调用终端操作时才会执行。这使得流可以进行优化。
-
无副作用:
Stream操作一般是无状态和无副作用的,也就是说,它们不影响原始的数据源。
3. Stream 的基本操作类型
Stream 主要由两类操作组成:
- 中间操作(Intermediate Operations):返回一个新的 Stream。这类操作是惰性求值的。
- 终端操作(Terminal Operations):产生结果或者副作用,执行后会结束流。
中间操作:
-
filter(Predicate<? super T> predicate):- 用于过滤数据,保留符合条件的元素。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); List<String> result = names.stream().filter(name -> name.startsWith("A")).collect(Collectors.toList()); // 输出: ["Alice"]
-
map(Function<? super T, ? extends R> mapper):- 将每个元素映射为另一个类型,可以进行类型转换。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<Integer> nameLengths = names.stream().map(String::length).collect(Collectors.toList()); // 输出: [5, 3, 7]
-
sorted(Comparator<? super T> comparator):- 对流中的元素进行排序,可以传入自定义的比较器。
- 例子:
List<String> names = Arrays.asList("Bob", "Alice", "Charlie"); List<String> sortedNames = names.stream().sorted().collect(Collectors.toList()); // 输出: ["Alice", "Bob", "Charlie"]
-
distinct():- 去除流中的重复元素。
- 例子:
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4); List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList()); // 输出: [1, 2, 3, 4]
-
limit(long maxSize):- 截取流中的前
maxSize个元素。 - 例子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> limitedNumbers = numbers.stream().limit(3).collect(Collectors.toList()); // 输出: [1, 2, 3]
- 截取流中的前
-
skip(long n):- 跳过前
n个元素,保留后面的元素。 - 例子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> skippedNumbers = numbers.stream().skip(2).collect(Collectors.toList()); // 输出: [3, 4, 5]
- 跳过前
终端操作:
-
forEach(Consumer<? super T> action):- 对流中的每个元素执行某种操作。注意,这是终端操作,一旦执行,流不再可用。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream().forEach(System.out::println);
-
collect(Collector<? super T, A, R> collector):- 用于将流中的元素收集到某种结果中,通常是
List、Set、Map等集合。 - 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<String> collectedNames = names.stream().collect(Collectors.toList());
- 用于将流中的元素收集到某种结果中,通常是
-
reduce(BinaryOperator<T> accumulator):- 对流中的元素进行累积操作,例如求和、求积等。
- 例子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4); int sum = numbers.stream().reduce(0, Integer::sum); // 输出: 10
-
count():- 返回流中元素的个数。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); long count = names.stream().count(); // 输出: 3
-
findFirst():- 返回流中的第一个元素。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Optional<String> firstName = names.stream().findFirst(); // 输出: Alice
-
anyMatch(Predicate<? super T> predicate):- 流中是否有任意元素匹配给定的条件。
- 例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); boolean hasAlice = names.stream().anyMatch(name -> name.equals("Alice")); // 输出: true
4. Stream API 的工作原理
Stream API 的工作过程分为三个主要步骤:
-
创建流:从集合或数组生成流对象。
- 可以通过
Collection接口中的stream()方法,或Arrays.stream()方法创建流。
- 可以通过
-
中间操作:链式调用的中间操作不会立即执行,而是建立处理流水线,直到终端操作触发整个流程。
-
终端操作:一旦调用终端操作,流中的数据处理开始执行,产生结果,整个 Stream 不再可用。
5. 并行流(Parallel Streams)
Java 8 中还引入了 并行流 的概念,可以通过 parallelStream() 方法或 stream().parallel() 创建。并行流将任务分割并分配给多个线程,提高大数据量下的处理性能。
例子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().reduce(0, Integer::sum);
并行流适合大规模数据集和计算密集型任务,但并非总是比顺序流快。应根据具体情况测试其性能。
6. Stream API 使用的最佳实践
-
尽量使用中间操作而不是修改外部变量:流操作应该是无副作用的,尽量不要在中间操作中修改外部变量。
-
避免不必要的并行流:并行流不总是能提高性能,特别是在小数据集上。
-
善用短路操作:
findFirst()、anyMatch()等操作会在找到结果时提前结束流的处理,适用于需要快速得到结果的场景。
7. Stream API 的优点
- 提高代码可读性:通过函数式编程的方式处理数据,简化了传统命令式编程中的冗余代码。
- 支持并行处理:并行流提供了处理大数据集的高效手段。
- 代码简洁:通过链式操作,使得代码更加紧凑、简洁。
8. 总结
Stream API 是 Java 8 引入的一项强大功能,它简化了集合的处理方式,支持声明式编程、无副作用操作,并具备强大的并行处理能力。掌握它能够帮助开发者写出更简洁、高效的代码。在实际使用中,需要根据具体场景选择合适的流操作
方式,提升应用程序的性能和可维护性。
记忆秘诀:
- 流 是数据流转的过程,不存储数据,只传递、处理数据。
- 中间操作 总是惰性求值,等到 终端操作 执行时,才真正处理数据。
相关文章:
Java Stream API 详解
Java Stream API 详解 1. 什么是 Stream API? Stream API 是 Java 8 引入的一种用于处理集合(如数组、列表)的强大工具。它提供了一种声明性方式处理数据,可以简化代码并提高可读性。Stream 不是数据结构,它只是一种…...
一文了解大模型中的SDK和API
大白话聊SDK和API-知乎 1.智谱AI的SDK和API 以智谱AI为例,智谱AI的SDK是名为zhipuai的Python包,其中包含了用于访问API的接口(如api-key)。在这个框架中,API是SDK的一部分,用于实现与智谱AI服务的交互。 …...
element plus的el-select分页
摘要: el-select的数据比较多的时候,必须要分页,处理方案有全部数据回来,或者添加搜索功能,但是就有个问题就是编辑的时候回显问题,必须要保证select的数据有对应的id与name匹配回显! <el-fo…...
STM32CubeMX【串口收发USART】
第一步,配置cubemx 配置好点右上角生成 第二步,串口方式 阻塞式发送 英文、中文正常、浮点有口 /* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();//配置完自动生成的 发送到串口助手上 while (1){/* USER CODE…...
【学术会议投稿】Java Web开发实战:从零到一构建动态网站
【会后3-4个月检索|IEEE出版】第五届人工智能与计算机工程国际学术会议(ICAICE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看: https://ais.cn/u/nuyAF3 目录 引言 一、Java Web开发基础 1. Java Web开发简介 2. 开发环境搭建 …...
[Unity]内存优化
参考: Unity 内存优化 | 新诸子Unity内存优化(来自uwa) - weigang - 博客园Unity游戏内存优化——以TileMatch为例https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/OptimizationMemory.mdunity内存…...
FreeRTOS工程创建,创建多任务程序,基于汇编对ARM架构的简单理解
FreeRTOS工程创建 下载STM32CubeMX尽量找网盘下载(只是建议,没有说官网不行) 1.创建 STM32CubeMX 工程 (1)双击运行 STM32CubeMX,在首页面选择“Access to MCU Selector”,如下图所示࿱…...
C++STL--------list
文章目录 一、list链表的使用1、迭代器2、头插、头删3、insert任意位置插入4、erase任意位置删除5、push_back 和 pop_back()6、emplace_back尾插7、swap交换链表8、reverse逆置9、merge归并10、unique去重11、remove删除指定的值12、splice把一个链表的结点转移个另一个链表13…...
M1 Mac打开Jupyter notebook
当我成功安装了Jupyter之后,发现无法通过 jupyter notebook 开始工作。 最初的问题是 zsh command not found 该问题是个路径问题,通过添加PATH环境变量就行了,设置环境变量时需要注意,zshrc和bash_profile中都可以设置&…...
docker 仓库之harbor详解
Harbor 是一个开源的企业级容器镜像仓库,由 VMware 提供。它基于 Docker 分布式应用程序框架构建,旨在解决企业对容器镜像存储、安全性和可管理性的需求。Harbor 提供了丰富的功能,包括用户权限管理、镜像复制、审计日志、漏洞扫描等…...
【环境变量】windons的Path
在 Windows 操作系统中,“Path” 是一个重要的环境变量,它定义了操作系统在执行命令时搜索可执行文件的目录。简而言之,当你在命令行(例如 cmd 或 PowerShell)中输入一个命令时,Windows 会查看 “Path” 环…...
go语言里的切片
package mainimport "fmt"func main() {// 创建一个长度为3,容量为5的整数切片var numbers make([]int, 3, 8)// 打印初始状态printSlice(numbers) // 输出: len3 cap5 slice[0 0 0]// 向切片添加元素numbers append(numbers, 1, 2)// 再次打印…...
革新你的智能体验:AIStarter 3.1.1正式版现已上线【安全认证】ai应用市场,数字人,ai绘画,ai视频,大模型,工作流因有尽有
在这个日新月异的技术时代里,人工智能(AI)正以前所未有的速度改变着我们的生活与工作方式。作为行业内的先锋之一,我们非常高兴地宣布:经过团队不懈努力以及严格的测试与优化后,AIStarter 3.1.1新版现已震撼…...
【练习17】数组中的最长连续子序列
数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com) 题目分析:排序双指针 排序后,判断是否连续:后一个数-前一个数1 排序后,判断是否重复:后一个数-前一个数0 public class Solution {public int MLS (int[] arr)…...
2024 最适合 Web 开发者的 9 款 Chrome 扩展
随着 2024 年的进展,Chrome 扩展程序已成为 Web 开发人员工具包中不可或缺的一部分,在浏览器中提供强大的功能。在这篇文章中,我们将探讨今年在 Web 开发社区掀起波澜的 9 大 Chrome 扩展程序。 1.Lighthouse https://chromewebstore.google…...
React综合指南(二)
https://activity.csdn.net/creatActivity?id10787 #1024程序员节|征文# 21、 React中的状态是什么?它是如何使用的?? 状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现…...
XML\XXE漏洞基本原理
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理XXE漏洞的相应信息 XML与XXE漏洞 这个东西有许多叫法,XML漏洞与XXE漏洞差不多都是一个东西。 这个漏洞是出现在XMl上的,然后可以叫他XXE注入漏洞。 XML简介 XML是一种数据的传输…...
uniapp小程序自定义聚合点
注: 1.默认的聚合点可以点击自动展示子级点位,但是自定义的聚合点在ios上无法触发markerClusterClick的监听,至今未解决,不知啥原因 2.ios和安卓展示的点位样式还有有差别 源码附上 <template><view class"marke…...
Spring Boot在线考试系统:JavaWeb技术的应用案例
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
Linux在服务器多节点下面如何快速查找日志
背景:最近在查找一个核心服务的后台日志,发现竟然部署了十几个节点,而且没使用ELK来做日志处理,所以查找日志非常不方便,不可能一个服务节点一个服务地找,所以通过同事间互相沟通找到一个方法,通…...
NY345固态MT29F32T08GWLBHD6-24T:B
NY345固态MT29F32T08GWLBHD6-24T:B在智能制造、交通控制、能源监测等关键领域,每一次写入与读取都决定着系统运行的可靠性。美光(Micron)MT29F32T08GWLBHD6-24T:B,以其32Tb大容量、工业级封装和多模式灵活切换,成为嵌入…...
实测测评|零注册AI PDF翻译工具:保留排版\+OCR无损翻译,替代DeepL/谷歌翻译
在日常开发、学术科研、外文文献研读场景中,PDF翻译一直是高频刚需痛点。市面上主流的翻译工具普遍存在排版错乱、OCR收费、文件大小受限、强制登录注册等问题,尤其是学术论文、带表格/公式的技术手册、扫描版外文资料,翻译后的可用性极差。 …...
别再手动分片了!用SeaweedFS的Chunk机制搞定海量小文件存储(Docker实战)
别再手动分片了!用SeaweedFS的Chunk机制搞定海量小文件存储(Docker实战) 当你的图片上传服务每天新增百万级文件时,传统存储方案往往会突然"罢工"——目录遍历耗时从秒级飙升到分钟级,inode耗尽导致服务崩溃…...
告别轮询!手把手教你用S32K3的FlexCAN Enhanced FIFO+DMA实现高效CAN FD数据接收
告别轮询!手把手教你用S32K3的FlexCAN Enhanced FIFODMA实现高效CAN FD数据接收 在汽车电子和工业控制领域,CAN FD总线的高负载场景对MCU的实时性提出了严苛挑战。当波特率飙升至5Mbps、单帧数据扩展到64字节时,传统的中断接收模式会让CPU陷入…...
Spring事件驱动:从@EventListener源码到高并发实践
1. Spring事件驱动机制入门 第一次接触Spring事件驱动时,我完全被各种Listener和Event搞晕了。直到在电商项目中遇到用户注册后需要执行多个后续操作的需求,才真正理解它的价值。想象一下,用户注册成功后需要发送短信、发放优惠券、记录行为日…...
物联网平台融资潮解析:从资本流向看行业技术演进与未来格局
1. 项目概述:为什么我们要关注物联网平台的融资潮?最近几年,如果你在科技圈里待着,很难不注意到一个现象:那些做物联网开发平台的公司,动不动就宣布完成了上亿甚至数亿美元的融资。这已经不是个别现象&…...
MMAUD:面向现代微型无人机威胁的全面多模态反无人机数据集
摘要 https://arxiv.org/pdf/2402.03706 针对小型无人机(UAV)不断演变的挑战(其具备运输有害载荷或独立造成破坏的潜力),我们推出了 MMAUD:一个全面的多模态反无人机数据集。MMAUD 通过专注于无人机检测、无…...
边缘金融大语言模型的高效部署与实时推理优化
1. 边缘金融大语言模型的技术背景与挑战金融行业每天产生海量非结构化数据,包括客户咨询记录、财报文本、新闻舆情等。传统NLP模型在处理这类数据时面临两个核心痛点:一是无法理解金融专业术语背后的复杂语义(如"可转债"在不同上下…...
从Simulink到Tina:硬件工程师如何更“接地气”地获取电路传递函数?
从Simulink到Tina:硬件工程师如何更“接地气”地获取电路传递函数? 在系统级仿真与PCB调试的鸿沟之间,硬件工程师常常面临一个尴尬的现实:Simulink的数值解虽然精确,却像黑箱般难以直接指导电路板上电阻电容的调整。当…...
VIGOR:跨越“一对一”检索的理想假设,面向真实场景的跨视角地理定位数据集
一、数据集背景与开创性意义 VIGOR (Cross-View Image Geo-localization beyond One-to-one Retrieval) 是一个面向真实世界应用的全新大规模跨视角图像地理定位基准数据集,由 Sijie Zhu, Taojiannan Yang 和 Chen Chen 提出,相关论文发表于 CVPR 2021。…...
