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

Steam流

Steam流

Stream 流是什么,为什么要用它?

  • Stream是 Java8 新引入的一个包( java.util.stream),它让我们能用声明式的方式处理数据(集合、数组等)。
  • Stream流式处理相较于传统方法简洁高效,也便于进行并发编程。

Stream 是 Java8 的一大亮点,是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的聚合操作(aggregate operation)或者大批量数据操作。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

同时,它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。

所以说,Java8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

Stream 流的使用

** 简单综合案例**

问题和需求:在一个字符串集合中找出以“阿”开头的长度为 3 的字符串并打印。

传统方法:
import java.util.ArrayList;
import java.util.List;public class Demo02NormalFilter {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("阿拉贡");list.add("阿尔玟");list.add("埃尔隆德");list.add("凯兰崔尔");list.add("瑟兰督伊");List<String> zhangList = new ArrayList<>();for (String name : list) {if (name.startsWith("阿")) {zhangList.add(name);}}List<String> shortList = new ArrayList<>();for (String name : zhangList) {if (name.length() == 3) {shortList.add(name);}}for (String name : shortList) {System.out.println(name);}}
}

这里我们可以看到传统的方法中含有三个循环,每一个作用不同:

  • 首先筛选所有姓“阿”的人
  • 然后筛选名字有三个字的人
  • 最后进行对结果进行打印输出

这样的处理过程代码冗长,导致代码可读性较差,效率也比较低。而使用 Stream 来进行处理就能使代码优雅地多。

Stream 流式处理方法:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;public class Demo02NormalFilter {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("阿拉贡");list.add("阿尔玟");list.add("埃尔隆德");list.add("凯兰崔尔");list.add("瑟兰督伊");list.stream().filter(s ‐> s.startsWith("阿")).filter(s ‐> s.length() == 3).forEach(System.out::println);}
}

利用 Stream 流中的方法再结合函数式接口和 Lambda 表达式,我们的代码就能变得格外简洁明了。

** 获取流**

①根据 Collection 获取流

首先,java.util.Collection 接口中加入了 default 方法 stream 用来获取流,所以其所有实现类均可获取流。

import java.util.*;
import java.util.stream.Stream;public class Demo04GetStream {public static void main(String[] args) {List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set = new HashSet<>();Stream<String> stream2 = set.stream();Vector<String> vector = new Vector<>();Stream<String> stream3 = vector.stream();}
}

②根据 Map 获取流

java.util.Map 接口不是 Collection 的子接口,且其 K-V 数据结构不符合流元素的单一特征,所以获取对应的流需要分 key、value 或 entry 等情况:

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;public class Demo05GetStream {public static void main(String[] args) {Map<String, String> map = new HashMap<>();//Stream流的转化需要单列数据,那么我们就先把map里面的数据变成单列的再转化为流Stream<String> keyStream = map.keySet().stream();Stream<String> valueStream = map.values().stream();Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();}
}

③根据数组获取流

如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法 of ,使用很简单:

import java.util.stream.Stream;public class Demo06GetStream {public static void main(String[] args) {String[] array = { "阿拉贡", "阿尔玟", "埃尔隆德", "凯兰崔尔""瑟兰督伊" };Stream<String> stream = Stream.of(array);}
}

** 常用方法**

流模型的操作很丰富,这里介绍一些常用的 API。

这些方法可以被分成两种:

  • **延迟方法:**返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法)
  • **终结方法:**返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。(如果想知道更多方法,建议自行参考 API 文档)

接下来我会介绍两个终结方法 count 和 forEach 方法。

①逐一处理:forEach

虽然方法名字叫 forEach ,但是与 for 循环中的“for-each”语句是不一样的,该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。

方法签名:
void forEach(Consumer<? super T> action);
基本使用:
import java.util.stream.Stream;public class Demo12StreamForEach {public static void main(String[] args) {Stream<String> stream = Stream.of("阿拉贡", "阿尔玟", "埃尔隆德");stream.forEach(name‐> System.out.println(name));}
}
筛选:filter

可以通过 filter 方法将一个流转换成另一个子集流。该方法接收一个 Predicate 函数式接口参数(可以是一个 Lambda 或方法引用)作为筛选条件。

方法签名:
Stream<T> filter(Predicate<? super T> predicate);
基本使用:
import java.util.stream.Stream;public class Demo07StreamFilter {public static void main(String[] args) {Stream<String> original = Stream.of("阿拉贡", "阿尔玟", "埃尔隆德");Stream<String> result = original.filter(s ‐> s.startsWith("阿"));}
}

在这里通过 Lambda 表达式来指定了筛选的条件:必须以“阿”开头。

映射:map

如果需要将流中的元素映射到另一个流中,可以使用 map 方法。该接口需要一个 Function 函数式接口参数,可以将当前流中的 T 类型数据转换为另一种 R 类型的流。

方法签名:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
基本使用:
import java.util.stream.Stream;public class Demo08StreamMap {public static void main(String[] args) {Stream<String> original = Stream.of("10", "12", "18");Stream<Integer> result = original.map(str‐>Integer.parseInt(str));}
}

这段代码中, map 方法的参数通过方法引用,将字符串类型转换成为了 int 类型(并自动装箱为 Integer 类对象)。

统计个数:count

正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数。该方法返回一个 long 值代表元素个数(不再像旧集合那样是 int 值)。

方法签名:
long count();
基本使用:
import java.util.stream.Stream;public class Demo09StreamCount {public static void main(String[] args) {Stream<String> original = Stream.of("阿拉贡", "阿尔玟", "埃尔隆德");Stream<String> result = original.filter(s ‐> s.startsWith("阿"));System.out.println(result.count()); // 2}
}
取用前几个:limit

limit 方法可以对流进行截取,只取用前 n 个。参数是一个 long 型,如果集合当前长度大于参数则进行截取;否则不进行操作。

方法签名:
Stream<T> limit(long maxSize);
基本使用:
import java.util.stream.Stream;public class Demo10StreamLimit {public static void main(String[] args) {Stream<String> original = Stream.of("阿拉贡", "阿尔玟", "埃尔隆德");Stream<String> result = original.limit(2);System.out.println(result.count()); // 2}
}
跳过前几个:skip

如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流。如果流的当前长度大于 n,则跳过前 n 个;否则将会得到一个长度为 0 的空流。

方法签名:
Stream<T> skip(long n);
基本使用:
import java.util.stream.Stream;public class Demo11StreamSkip {public static void main(String[] args) {Stream<String> original = Stream.of("阿拉贡", "阿尔玟", "埃尔隆德");Stream<String> result = original.skip(2);System.out.println(result.count()); // 1}
}
②组合:concat

如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat。

这是一个静态方法,与 java.lang.String 当中的 concat 方法是不同的。

方法签名:
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T>b)
基本使用:
import java.util.stream.Stream;public class Demo12StreamConcat {public static void main(String[] args) {Stream<String> streamA = Stream.of("阿拉贡");Stream<String> streamB = Stream.of("阿尔玟");Stream<String> result = Stream.concat(streamA, streamB);}
}

相关文章:

Steam流

Steam流 Stream 流是什么&#xff0c;为什么要用它&#xff1f; Stream是 Java8 新引入的一个包&#xff08; java.util.stream&#xff09;&#xff0c;它让我们能用声明式的方式处理数据&#xff08;集合、数组等&#xff09;。Stream流式处理相较于传统方法简洁高效&#…...

Nuxt实战教程基础-Day01

Nuxt实战教程基础-Day01Nuxt是什么&#xff1f;Nuxt.js框架是如何运作的&#xff1f;Nuxt特性流程图服务端渲染(通过 SSR)单页应用程序 (SPA)静态化 (预渲染)Nuxt优缺点优点缺点安装运行项目总结前言&#xff1a;本教程基于Nuxt2&#xff0c;作为教程的第一天&#xff0c;我们先…...

栈和队列详细讲解+算法动画

栈和队列 栈stack 栈也是一种线性结构相比数组&#xff0c;栈对应的操作数数组的子集只能从一端添加元素&#xff0c;也只能从一端取出元素这一端称为栈顶 栈是一种后进先出的数据结构Last in Firt out(LIFO)在计算机的世界里&#xff0c;栈拥有者不可思议的作用 栈的应用 …...

【Unity3D小技巧】Unity3D中判断Animation以及Animator动画播放结束,以及动画播放结束之后执行函数

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在日常开发中&#xff0c;可能会遇到要判断Animation或者Anima…...

【1】熟悉刷题平台操作

TestBench使用 与quartus中testbench的写法有些许。或者说这是平台特有的特性&#xff01;&#xff01; 1 平台使用谨记 &#xff08;1&#xff09;必须删除&#xff1a;若设计为组合逻辑&#xff0c;需将自动生成的clk删除 若不删除&#xff0c;会提示运行超时错误。 &#…...

计算机网络:RIP协议以及距离向量算法

RIP协议 RIP是一种分布式的基于适量向量的路由选择协议&#xff0c;最大优点是简单。要求网络中的每一个路由器都要维护从它自己到其他每一个目的网络的唯一最佳&#xff08;最短&#xff09;距离记录&#xff0c;最多包含15个路由器&#xff0c;距离为16就表示网络不可达&…...

[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)

1. 简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。 数据 数据是客观事物的符号表示&#xff0c;是所有能输人到计算机中并被计算机程序处理的符号的总称。数据是信息的载体&#xff0c;能够被计算机识别、存储和加工 数据元素…...

JS_countup.js 的简单使用,数字滚动效果

countup.js countup.js 是一个轻量级&#xff0c;无依赖的JavaScript类&#xff0c;通过简单的设置就可以达到数字滚动的效果 官网&#xff1a;https://inorganik.github.io/countUp.js/ 源码 var CountUpfunction(target,startVal,endVal,decimals,duration,options){var …...

【C++知识点】STL 容器总结

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…...

C++---背包模型---装箱问题(每日一道算法2023.3.9)

注意事项&#xff1a; 本题是"动态规划—01背包"的扩展题&#xff0c;dp和优化思路不多赘述。 题目&#xff1a; 有一个箱子容量为 V&#xff0c;同时有 n 个物品&#xff0c;每个物品有一个体积&#xff08;正整数&#xff09;。 要求 n 个物品中&#xff0c;任取若…...

if-else if与switch的练习1:输入两个数,输出两个数的加减乘除的值

1.if-else if的练习 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice…...

【教程】你现在还不知道微软的New Bing?你out了,快点进来看

哈喽啊&#xff0c;大家好&#xff0c;好久不见&#xff0c;我是木易巷&#xff01; 不禁感叹&#xff0c;AI人工智能时代真的已经来临&#xff01; 目前&#xff0c;谷歌和微软就各自面向大众的产品发布了重大公告。谷歌推出了一款名为Bard实验性对话式 AI 服务&#xff0c;而…...

https流程

ssl加密协议包含以下4个步骤 1、服务器去第三方机构注册生成证书&#xff0c;第三方机构非对称加密生成公钥私钥&#xff0c;给服务器一个私钥&#xff0c;证书包含了公钥。 2、客户端向服务器索要证书 3、客户端向第三方机构验证证书 4、客户端对称加密生成密钥&#xff0c;在…...

python魔法方法

Python中的魔法方法&#xff08;也称为特殊方法或双下划线方法&#xff09;是在类定义中使用的一些特殊的函数,可以使用dir方法查询。它们以双下划线开头和结尾&#xff0c;例如__init__和__str__。这些方法被Python解释器用于执行特定的操作&#xff0c;例如实例化对象、字符串…...

软件测试员如何进行产品测试?

一般来讲&#xff0c;当软件成为一个成功的产品后&#xff0c;产品测试工作就会复杂很多。比如拥有的用户量大&#xff0c;迭代频繁&#xff0c;测试的周期短&#xff0c;重复性强。面对紧张复杂的产品测试工作&#xff0c;软件测试员应怎样完成这一系列的测试工作呢&#xff1…...

计算机网络基础知识点【1】

文章目录计算机网络第一章 计算机网络参考模型1.计算机网络为什么需要分层&#xff1f;1.1 分层思想1.2 分层好处2.OSI七层模型2.1 OSI七层模型总结2.2 OSI七层工作原理2.3 数据封装与解封装2.4 计算机网络常用协议3.TCP/IP参考模型3.1 什么是TCP/IP协议3.2 TCP/IP协议族的组成…...

c++ 中标准库类型 string 详解

&#x1f441;‍&#x1f5e8;&#x1f441;‍&#x1f5e8; 前言 标准库类型string 表示可变长的字符序列&#xff0c;使用string 类型必须首先包含string 头文件。string 定义在命名空间std 中。 定义和初始化 string 对象 首先说明如何初始化对象是由类本身决定的&#xff0…...

Html新增属性之拖拽(drag)

元素在拖放过程中触发的事件 HTML5中&#xff0c;只要将元素的 draggable 属性设置为 true 就可以实现拖放功能&#xff0c;在拖放过程中&#xff0c;触发了多个事件&#xff0c;如下&#xff1a; dragstart:事件主体是被拖放元素&#xff0c;在开始拖放被拖放元素时触发。dra…...

C/C++开发,无可避免的多线程(篇二).thread与其支持库

一、原子类型与原子操作 1.1 原子类型与操作介绍 在前一篇博文中&#xff0c;多线程交互示例代码中&#xff0c;给出了一个原子类型定义&#xff1a; // 原子数据类型 atomic_llong total {0}; 那么什么事原子数据类型呢&#xff0c;和c的基础数据类型有什么不同呢&#xff1a…...

mysql数据库之表级锁

表级锁&#xff0c;每次操作锁住整张表。锁定粒度大&#xff0c;发生所冲突的概率最高&#xff0c;并发度最低。应用在myisam、innodb、bdb等存储引擎中。 一、表级锁分类。 1、表锁 2、元数据锁&#xff08;meta data lock&#xff0c;MDL&#xff09; 3、意向锁 二、表锁…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...