当前位置: 首页 > news >正文

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 主要由两类操作组成:

  1. 中间操作(Intermediate Operations):返回一个新的 Stream。这类操作是惰性求值的。
  2. 终端操作(Terminal Operations):产生结果或者副作用,执行后会结束流。
中间操作:
  1. 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"]
      
  2. 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]
      
  3. 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"]
      
  4. 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]
      
  5. 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]
      
  6. 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]
      
终端操作:
  1. forEach(Consumer<? super T> action)

    • 对流中的每个元素执行某种操作。注意,这是终端操作,一旦执行,流不再可用。
    • 例子:
      List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
      names.stream().forEach(System.out::println);
      
  2. collect(Collector<? super T, A, R> collector)

    • 用于将流中的元素收集到某种结果中,通常是 ListSetMap 等集合。
    • 例子:
      List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
      List<String> collectedNames = names.stream().collect(Collectors.toList());
      
  3. reduce(BinaryOperator<T> accumulator)

    • 对流中的元素进行累积操作,例如求和、求积等。
    • 例子:
      List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
      int sum = numbers.stream().reduce(0, Integer::sum);
      // 输出: 10
      
  4. count()

    • 返回流中元素的个数。
    • 例子:
      List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
      long count = names.stream().count();
      // 输出: 3
      
  5. findFirst()

    • 返回流中的第一个元素。
    • 例子:
      List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
      Optional<String> firstName = names.stream().findFirst();
      // 输出: Alice
      
  6. 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 的工作过程分为三个主要步骤:

  1. 创建流:从集合或数组生成流对象。

    • 可以通过 Collection 接口中的 stream() 方法,或 Arrays.stream() 方法创建流。
  2. 中间操作:链式调用的中间操作不会立即执行,而是建立处理流水线,直到终端操作触发整个流程。

  3. 终端操作:一旦调用终端操作,流中的数据处理开始执行,产生结果,整个 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 使用的最佳实践
  1. 尽量使用中间操作而不是修改外部变量:流操作应该是无副作用的,尽量不要在中间操作中修改外部变量。

  2. 避免不必要的并行流:并行流不总是能提高性能,特别是在小数据集上。

  3. 善用短路操作findFirst()anyMatch() 等操作会在找到结果时提前结束流的处理,适用于需要快速得到结果的场景。

7. Stream API 的优点
  1. 提高代码可读性:通过函数式编程的方式处理数据,简化了传统命令式编程中的冗余代码。
  2. 支持并行处理:并行流提供了处理大数据集的高效手段。
  3. 代码简洁:通过链式操作,使得代码更加紧凑、简洁。
8. 总结

Stream API 是 Java 8 引入的一项强大功能,它简化了集合的处理方式,支持声明式编程、无副作用操作,并具备强大的并行处理能力。掌握它能够帮助开发者写出更简洁、高效的代码。在实际使用中,需要根据具体场景选择合适的流操作

方式,提升应用程序的性能和可维护性。

记忆秘诀

  • 是数据流转的过程,不存储数据,只传递、处理数据。
  • 中间操作 总是惰性求值,等到 终端操作 执行时,才真正处理数据。

相关文章:

Java Stream API 详解

Java Stream API 详解 1. 什么是 Stream API&#xff1f; Stream API 是 Java 8 引入的一种用于处理集合&#xff08;如数组、列表&#xff09;的强大工具。它提供了一种声明性方式处理数据&#xff0c;可以简化代码并提高可读性。Stream 不是数据结构&#xff0c;它只是一种…...

一文了解大模型中的SDK和API

大白话聊SDK和API-知乎 1.智谱AI的SDK和API 以智谱AI为例&#xff0c;智谱AI的SDK是名为zhipuai的Python包&#xff0c;其中包含了用于访问API的接口&#xff08;如api-key&#xff09;。在这个框架中&#xff0c;API是SDK的一部分&#xff0c;用于实现与智谱AI服务的交互。 …...

element plus的el-select分页

摘要&#xff1a; el-select的数据比较多的时候&#xff0c;必须要分页&#xff0c;处理方案有全部数据回来&#xff0c;或者添加搜索功能&#xff0c;但是就有个问题就是编辑的时候回显问题&#xff0c;必须要保证select的数据有对应的id与name匹配回显&#xff01; <el-fo…...

STM32CubeMX【串口收发USART】

第一步&#xff0c;配置cubemx 配置好点右上角生成 第二步&#xff0c;串口方式 阻塞式发送 英文、中文正常、浮点有口 /* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();//配置完自动生成的 发送到串口助手上 while (1){/* USER CODE…...

【学术会议投稿】Java Web开发实战:从零到一构建动态网站

【会后3-4个月检索|IEEE出版】第五届人工智能与计算机工程国际学术会议&#xff08;ICAICE 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看&#xff1a; https://ais.cn/u/nuyAF3 目录 引言 一、Java Web开发基础 1. Java Web开发简介 2. 开发环境搭建 …...

[Unity]内存优化

参考&#xff1a; Unity 内存优化 | 新诸子Unity内存优化&#xff08;来自uwa&#xff09; - weigang - 博客园Unity游戏内存优化——以TileMatch为例https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/OptimizationMemory.mdunity内存…...

FreeRTOS工程创建,创建多任务程序,基于汇编对ARM架构的简单理解

FreeRTOS工程创建 下载STM32CubeMX尽量找网盘下载&#xff08;只是建议&#xff0c;没有说官网不行&#xff09; 1.创建 STM32CubeMX 工程 &#xff08;1&#xff09;双击运行 STM32CubeMX&#xff0c;在首页面选择“Access to MCU Selector”&#xff0c;如下图所示&#xff1…...

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之后&#xff0c;发现无法通过 jupyter notebook 开始工作。 最初的问题是 zsh command not found 该问题是个路径问题&#xff0c;通过添加PATH环境变量就行了&#xff0c;设置环境变量时需要注意&#xff0c;zshrc和bash_profile中都可以设置&…...

docker 仓库之harbor详解

Harbor 是一个开源的企业级容器镜像仓库&#xff0c;由 VMware 提供。它基于 Docker 分布式应用程序框架构建&#xff0c;旨在解决企业对容器镜像存储、安全性和可管理性的需求。Harbor 提供了丰富的功能&#xff0c;包括用户权限管理、镜像复制、审计日志、漏洞扫描等&#xf…...

【环境变量】windons的Path

在 Windows 操作系统中&#xff0c;“Path” 是一个重要的环境变量&#xff0c;它定义了操作系统在执行命令时搜索可执行文件的目录。简而言之&#xff0c;当你在命令行&#xff08;例如 cmd 或 PowerShell&#xff09;中输入一个命令时&#xff0c;Windows 会查看 “Path” 环…...

go语言里的切片

package mainimport "fmt"func main() {// 创建一个长度为3&#xff0c;容量为5的整数切片var numbers make([]int, 3, 8)// 打印初始状态printSlice(numbers) // 输出: len3 cap5 slice[0 0 0]// 向切片添加元素numbers append(numbers, 1, 2)// 再次打印&#xf…...

革新你的智能体验:AIStarter 3.1.1正式版现已上线【安全认证】ai应用市场,数字人,ai绘画,ai视频,大模型,工作流因有尽有

在这个日新月异的技术时代里&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变着我们的生活与工作方式。作为行业内的先锋之一&#xff0c;我们非常高兴地宣布&#xff1a;经过团队不懈努力以及严格的测试与优化后&#xff0c;AIStarter 3.1.1新版现已震撼…...

【练习17】数组中的最长连续子序列

数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com) 题目分析&#xff1a;排序双指针 排序后&#xff0c;判断是否连续&#xff1a;后一个数-前一个数1 排序后&#xff0c;判断是否重复&#xff1a;后一个数-前一个数0 public class Solution {public int MLS (int[] arr)…...

2024 最适合 Web 开发者的 9 款 Chrome 扩展

随着 2024 年的进展&#xff0c;Chrome 扩展程序已成为 Web 开发人员工具包中不可或缺的一部分&#xff0c;在浏览器中提供强大的功能。在这篇文章中&#xff0c;我们将探讨今年在 Web 开发社区掀起波澜的 9 大 Chrome 扩展程序。 1.Lighthouse https://chromewebstore.google…...

React综合指南(二)

https://activity.csdn.net/creatActivity?id10787 #1024程序员节&#xff5c;征文# 21、 React中的状态是什么&#xff1f;它是如何使用的&#xff1f;&#xff1f; 状态是 React 组件的核心&#xff0c;是数据的来源&#xff0c;必须尽可能简单。基本上状态是确定组件呈现…...

XML\XXE漏洞基本原理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理XXE漏洞的相应信息 XML与XXE漏洞 这个东西有许多叫法&#xff0c;XML漏洞与XXE漏洞差不多都是一个东西。 这个漏洞是出现在XMl上的&#xff0c;然后可以叫他XXE注入漏洞。 XML简介 XML是一种数据的传输…...

uniapp小程序自定义聚合点

注&#xff1a; 1.默认的聚合点可以点击自动展示子级点位&#xff0c;但是自定义的聚合点在ios上无法触发markerClusterClick的监听&#xff0c;至今未解决&#xff0c;不知啥原因 2.ios和安卓展示的点位样式还有有差别 源码附上 <template><view class"marke…...

Spring Boot在线考试系统:JavaWeb技术的应用案例

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…...

Linux在服务器多节点下面如何快速查找日志

背景&#xff1a;最近在查找一个核心服务的后台日志&#xff0c;发现竟然部署了十几个节点&#xff0c;而且没使用ELK来做日志处理&#xff0c;所以查找日志非常不方便&#xff0c;不可能一个服务节点一个服务地找&#xff0c;所以通过同事间互相沟通找到一个方法&#xff0c;通…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...