【Java学习】Stream流详解
所属专栏:Java学习
Stream流是JDK 8引入的一个概念,它提供了一种高效且表达力强的方式来处理数据集合(如List、Set等)或数组。Stream API可以以声明性方式(指定做什么)来处理数据序列。流操作可以被分为两大类:中间操作(Intermediate Operations)和终端操作(Terminal Operations)。
🍁1. Stream流的适用对象
先得到一条Stream流,并把数据放上去,再进行中间操作和终端操作
获取方式 | 方法名 | 说明 |
单列集合 | default Stream<E>stream() | Collection中的默认方法 |
双列集合 | 无 | 无法直接使用Stream流 |
数组 | public static <T> Stream<T> stream(T[] array) | Arrays工具类中的静态方法 |
一堆零散数据 | public static <T> Stream<T> of(T...values) | Stream接口中的静态方法 |
先来看单列集合的例子:
public class Demo1 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "a", "b", "c", "d", "e");// 获取Stream流,把集合中的数据放到流上Stream<String> stream1 = arrayList.stream();//内部类方式打印stream1.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s);}});System.out.println();//获取流之后直接通过lambda表达式进行打印arrayList.stream().forEach(s -> System.out.print(s));}
}
对于双列集合,需要通过keySet() 或 entrySet() 转化为单列集合,再获取Stream
public class Demo2 {public static void main(String[] args) {HashMap<String,Integer> hashMap = new HashMap<>();hashMap.put("aaa",1);hashMap.put("bbb",2);hashMap.put("ccc",3);hashMap.put("ddd",4);//双列集合第一种获取Stream流hashMap.keySet().stream().forEach(s -> System.out.print(s + " "));System.out.println();//双列集合第二种获取hashMap.entrySet().stream().forEach(s -> System.out.print(s + " "));}
}
数组获取Stream流:
public class Demo3 {public static void main(String[] args) {int[] arr1 = {1, 2, 3, 4, 5};String[] arr2 = {"a", "b", "c", "d"};//获取Stream流Arrays.stream(arr1).forEach(s-> System.out.print(s + " "));System.out.println();//数组中是引用型数据类型也可以获取Stream流Arrays.stream(arr2).forEach(s -> System.out.print(s + " "));}
}
对于不存储在数组或集合中的零散数据,可以直接通过Stream接口中的静态方法获取
public class Demo4 {public static void main(String[] args) {Stream.of(1,2,3,4,5).forEach(s-> System.out.print(s + " "));System.out.println();Stream.of("a","b","c").forEach(s-> System.out.print(s + " "));}
}
🍁2. 中间方法
中间操作:中间操作可以返回流本身,因此可以链式调用多个中间操作,中间操作可以是对流的过滤(如filter
)、映射(如map
)、排序(如sorted
)等
在上面的中间方法时,只会修改Stream流中的数据,不会影响原来集合或数组中的数据,并且原来的流只能使用一次
🍁2.1 filter()
filter 的参数 Predicate 是一个函数式接口 ,所以可以先使用匿名内部类的方式,再用 lambda 表达式
public class Demo5 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "aaa", "abc", "acb", "aa", "bb", "cc");//fitlter 过滤 把a开头的留下,其余数据不要arrayList.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//返回值为true,当前数据留下,返回值为false,当前数据舍弃return s.startsWith("a");}}).forEach(s -> System.out.print(s + " "));System.out.println();// lambda表达式的形式arrayList.stream().filter(s -> s.startsWith("a")).forEach(s -> System.out.print(s + " "));System.out.println();//把stream流暂时接收的方式Stream<String> stream1 = arrayList.stream().filter(s -> s.startsWith("a"));stream1.forEach(s -> System.out.print(s + " "));}
}
由于Stream流只能用一次,如果之前的流已经被使用过,再次使用就会报错
所以说,由于只能使用一次,再用一个变量取接收也没有什么意义,直接使用链式编程就可以了
并且,使用流之后,原来集合中的元素也不会改变
🍁2.2 limit() 和 skip()
/* limit() 获取前面几个元素skip() 跳过几个元素*/arrayList.stream().limit(3).forEach(s -> System.out.print(s + " "));System.out.println();arrayList.stream().skip(3).forEach(s -> System.out.print(s + " "));
🍁2.3 distinct()和concat()
distinct()去重是依赖hashCode()和equals()方法的,所以如果是自定义类型,要手动的重写这两个方法
public class Demo6 {public static void main(String[] args) {ArrayList<String> arrayList1 = new ArrayList<>();Collections.addAll(arrayList1, "aaa", "aaa", "acb", "aa", "bb", "cc");ArrayList<String> arrayList2 = new ArrayList<>();Collections.addAll(arrayList2,"dd","ee");//去重arrayList1.stream().distinct().forEach(s -> System.out.print(s + " "));System.out.println();//流的合并Stream.concat(arrayList1.stream(),arrayList2.stream()).forEach(s -> System.out.print(s + " "));}
}
🍁2.4 map()
需求:获取集合中的数字部分
首先调用split方法进行分割,得到数字部分之后再转换为整型
public class Demo7 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "aaa-11", "acb-22", "aa-33", "bb-44", "cc-55");// 获取集合中的数字部分arrayList.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {//使用split进行分割String[] arr = s.split("-");//获取数字部分String num = arr[1];//转换为int类型int ans = Integer.parseInt(num);return ans;}}).forEach(s -> System.out.print(s + " "));System.out.println();//lambda表达式arrayList.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.print(s + " "));}
}
🍁3. 终结方法
名称 | 说明 |
void forEach(Consumer action) | 遍历 |
long count() | 统计 |
toArray() | 收集流中的数据,放到数组中 |
collect(Collector collector) | 收集流中的数据,放到集合中 |
🍁3.1 forEach()和count()
forEach方法在之前已经演示过了,就是进行遍历的
forEach中的参数Consumer也是一个函数式接口,也可以先使用匿名内部类的方式,再用 lambda 表达式
public class Demo8 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "aaa", "aaa", "acb", "aa", "bb", "cc");arrayList.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + " ");}});System.out.println();arrayList.forEach(s-> System.out.print(s + " "));System.out.println();//统计个数long l = arrayList.stream().count();System.out.println(l);}
}
count() 的返回值为long类型的,可以定义一个变量进行接收
🍁3.2 toArray()
toArray()是收集流里面的数据放在数组中
toArray()方法有两种返回类型,一种是Object类型的,另一种是指定类型的,Object类型的比较简单,直接用Object类型的变量来接收就可以了
public class Demo9 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "aaa", "aaa", "acb", "aa", "bb", "cc");Object[] array1 = arrayList.stream().toArray();System.out.println(Arrays.toString(array1));}
}
接下来看指定类型
toArray方法的参数也是一个函数式接口,还是使用匿名内部类和lambda表达式两种方式演示
public class Demo9 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "aaa", "aaa", "acb", "aa", "bb", "cc");//IntFunction的泛型:具体类型的数组//apply方法的形参:流中数据的个数,返回的数组的长度要一致//返回值就是具体类型的数组String[] array2 = arrayList.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(array2));//lambda表达式String[] array = arrayList.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(array));}
}
IntFunction的泛型是具体类型的数组
apply方法的形参表示流中数据的个数,返回的数组的长度要一致,最后的返回值就是具体类型的数组
🍁3.3 collect()
collect() 方法就是收集流里面的数据放到集合中,下面先来演示收集到List和Set集合中的例子
public class Demo10 {public static void main(String[] args) {ArrayList<String> arrayList = new ArrayList<>();Collections.addAll(arrayList, "张三-男-23", "李四-男-21", "王五-女-22", "钱七-女-22");// 把所有男性收集起来//收集到List集合中List<String> list = arrayList.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());//收集到Set集合中Set<String> set = arrayList.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());}
}
收集到List和Set集合中的数据的区别还是和List和Set集合的区别一样的,Set集合中不能有重复的元素,如果流中收集的数据存在重复的数据,在收集到Set集合之后就会进行去重
接下来看Map集合,由于Map集合是一个双列集合,所以需要指定键和值的生成规则
这里的生成规则比较复杂
//收集到Map集合中/*** toMap : 参数一表示键的生成规则* 参数二表示值的生成规则* 参数一:* Function 泛型一:表示流中的数据类型* 泛型二:表示Map集合中键的类型* 方法 apply 形参:表示流中的每一个数据* 方法体:生成键的代码* 返回值:已经生成的键**/Map<String, Integer> map1 = arrayList.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(new Function<String, String>() {@Overridepublic String apply(String s) {return s.split("-")[0];}}, new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[2]);}}));System.out.println(map1);
//lambda表达式Map<String, Integer> map2 = arrayList.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));System.out.println(map2);
由于Map集合中是不能有重复的键的,所以如果Stream流获取的键中存在了重的元素,就会报错
🍁4. Stream流的作用和使用步骤总结
作用:Stream流就是结合了lambda表达式,简化集合和数组的操作
使用步骤:
1. 获取Stream流对象
2.使用中间方法处理数据
3.使用终结方法处理数据
相关文章:

【Java学习】Stream流详解
所属专栏:Java学习 Stream流是JDK 8引入的一个概念,它提供了一种高效且表达力强的方式来处理数据集合(如List、Set等)或数组。Stream API可以以声明性方式(指定做什么)来处理数据序列。流操作可以被分为两大…...
Oracle(69)什么是表压缩(Table Compression)?
表压缩(Table Compression)是一种数据库优化技术,用于减少表数据的存储空间和提高I/O性能。通过压缩表数据,可以显著减少存储需求,并在某些情况下提高查询性能,特别是对于只读或主要是读取操作的表。表压缩…...
java JUC编程
Java并发工具包(JUC),全称Java Util Concurrent,是Java提供的一个用于构建多线程应用程序的工具包,位于java.util.concurrent包及其子包中。 并发编程主要解决以下三个经典问题: 1. **原子性问题…...
vue3+element-plus表格分页选中加默认回显选中
1.需求 某个表单需要选择多条数据,点击选择按钮,弹框出来一个分页列表,选择多条数据,外面表单中显示选中的数据,可以删除数据,再次点击按钮,回显当前选中的数据。 2.解决办法 1.el-table加ro…...

Erupt 项目搭建
创建Spring Boot项目 Maven依赖 Spring Boot版本为 2.7.10,erupt版本为 1.12.14 erupt版本要与Spring Boot版本适配,3.x.x版本Spring Boot暂不适用说是 <properties><erupt.version>1.12.14</erupt.version></properties> <…...

HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…...

比特位的计算
给你一个整数 n ,对于 0 < i < n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n 1 的数组 ans 作为答案。 示例 1: 输入:n 2 输出:[0,1,1] 解释: 0 --> 0 1 --> …...

SQLAlchemy 学习笔记
通信类型:AF_INET 协议家族一般是表示TCP通信的SOC_STREAM和UDP通信的SOCK_DGRAM。对于TCP通信,建立socket连接,: s socket.socket(socket.AF_INET, socket.SOCK_STREAM)连接socket, s.connect((host,port))socket通信…...

Linux内核分析(调度类和调度实体)
文章目录 前言一、调度类1. stop_sched_class2. dl_sched_class3. rt_sched_class4. fair_sched_class5. idle_sched_class总结 二、调度类中的操作函数三、调度实体 前言 调度是操作系统内核的一个关键职责,它涉及到如何合理分配CPU时间给不同的进程或线程。在Lin…...
用输入输出流(I/O)流,递归复制和删除多级文件
一、(I/O)流递归复制一个文件 第一种: else if语句过多,看起来冗余,优点:多级文件一次性复制完整 import java.io.*;//数据源:src/main/java/day15_8_13/haha //目标;src/main/java/LaJi pub…...

kafka监控工具EFAK
kafka监控工具(EFAK) 1、下载2、解压3、配置3.1、安装数据库,需要mysql是,并创建ke数据库3.2、修改配置文件 4、启动4.1、启动zookeeper4.2、启动kafka4.3、启动EFAK 5、访问http://ip:8048 github地址:https://github…...

Page与自定义Components生命周期
自定义组件 自定义组件一般可以用component,装饰,在结构体里面用build方法定义UI,或者用builder装饰一个方法,来作为自定义组件的构造方法 而页面page一般用Entry,和component结合起来使用 页面生命周期方法: onPageShow:页面每次显示时触发 onPageHid…...

Chain of Thought (CoT) 系列论文:大模型思维链,提升 LLM 的推理能力
文章目录 1. COT:Chain of Thought1. 研究背景2. CoT的原理3. CoT Prompt 1. COT:Chain of Thought COT 是 2022.01 由 google 提出的针对提升 LLM 的推理能力的 Prompt Engineering 方法。 paper: Chain-of-Thought Prompting Elicits Re…...
已解决:java.net.BindException: 地址已在使用
1. 问题描述 java.net.BindException: 地址已在使用 是一种常见的网络异常,通常在服务器程序尝试绑定到一个已经被占用的端口或地址时出现。具体的异常信息可能如下: java.net.BindException: Address already in use: JVM_Bind或 java.net.BindExcep…...
看书标记【数据科学:R语言实战 8】
看书标记——R语言 Chapter 8 数据可视化——绘图8.1 功能包8.2 散点图8.2.1 回归线8.2.2 lowess线条8.2.3 scatterplot函数8.2.4 Scatterplot矩阵1.splom——展示矩阵数据2.cpairs——绘图矩阵图 8.2.5 密度散点图 8.3 直方图和条形图8.3.1 条形图8.3.2 直方图 8.3.3 ggplot28…...

STM32标准库学习笔记-1.基础知识
STM32介绍: STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ARM的含义: 公司名称:ARM公司成立于1990年,全称是Advanced RISC Machines(RISC:Reduced Instruction Set Computer 精简指令集计算机 相对应有C…...

Nginx:高效HTTP服务器与反向代理
Nginx:高效HTTP服务器与反向代理 1、核心特点2、应用场景 💖The Begin💖点点关注,收藏不迷路💖 Nginx,一个开源的HTTP服务器与反向代理工具,因其高性能、低资源消耗而备受推崇。以下是Nginx的几…...
vue3二次封装element-puls
将表单的通用信息给设置出来 如: label 的提示信息 , type 的类型 // 定义表单的配置项 const formConfig{ formItems:[ { type:"input", label:"用户ID", placeholder:"请输入用户ID" } ] } 页面配置如 <template v-for"(it…...
在CentOS 7上安装Apache Tomcat 8的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 介绍 Apache Tomcat 是一个用于提供 Java 应用程序的 Web 服务器和 Servlet 容器。Tomcat 是由 Apache 软件基金会发布的 Java Servlet…...

深入理解分布式事务中的三阶段提交(3PC),什么是3PC,3PC原理是怎样?3PC的优化?
在上一篇文章中,我们详细介绍了分布式事务中的两阶段提交,以及知道了两阶段提交存在一定的问题 深入理解分布式事务中的两阶段提交(2PC),什么是2PC,2PC原理是怎样?2PC有没有什么问题࿱…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...