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

【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流详解

所属专栏&#xff1a;Java学习 Stream流是JDK 8引入的一个概念&#xff0c;它提供了一种高效且表达力强的方式来处理数据集合&#xff08;如List、Set等&#xff09;或数组。Stream API可以以声明性方式&#xff08;指定做什么&#xff09;来处理数据序列。流操作可以被分为两大…...

Oracle(69)什么是表压缩(Table Compression)?

表压缩&#xff08;Table Compression&#xff09;是一种数据库优化技术&#xff0c;用于减少表数据的存储空间和提高I/O性能。通过压缩表数据&#xff0c;可以显著减少存储需求&#xff0c;并在某些情况下提高查询性能&#xff0c;特别是对于只读或主要是读取操作的表。表压缩…...

java JUC编程

Java并发工具包&#xff08;JUC&#xff09;&#xff0c;全称Java Util Concurrent&#xff0c;是Java提供的一个用于构建多线程应用程序的工具包&#xff0c;位于java.util.concurrent包及其子包中。 并发编程主要解决以下三个经典问题&#xff1a; 1. **原子性问题&#xf…...

vue3+element-plus表格分页选中加默认回显选中

1.需求 某个表单需要选择多条数据&#xff0c;点击选择按钮&#xff0c;弹框出来一个分页列表&#xff0c;选择多条数据&#xff0c;外面表单中显示选中的数据&#xff0c;可以删除数据&#xff0c;再次点击按钮&#xff0c;回显当前选中的数据。 2.解决办法 1.el-table加ro…...

Erupt 项目搭建

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

HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…...

比特位的计算

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

SQLAlchemy 学习笔记

通信类型&#xff1a;AF_INET 协议家族一般是表示TCP通信的SOC_STREAM和UDP通信的SOCK_DGRAM。对于TCP通信&#xff0c;建立socket连接&#xff0c;&#xff1a; s socket.socket(socket.AF_INET, socket.SOCK_STREAM)连接socket&#xff0c; s.connect((host,port))socket通信…...

Linux内核分析(调度类和调度实体)

文章目录 前言一、调度类1. stop_sched_class2. dl_sched_class3. rt_sched_class4. fair_sched_class5. idle_sched_class总结 二、调度类中的操作函数三、调度实体 前言 调度是操作系统内核的一个关键职责&#xff0c;它涉及到如何合理分配CPU时间给不同的进程或线程。在Lin…...

用输入输出流(I/O)流,递归复制和删除多级文件

一、&#xff08;I/O&#xff09;流递归复制一个文件 第一种&#xff1a; else if语句过多&#xff0c;看起来冗余&#xff0c;优点&#xff1a;多级文件一次性复制完整 import java.io.*;//数据源&#xff1a;src/main/java/day15_8_13/haha //目标;src/main/java/LaJi pub…...

kafka监控工具EFAK

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

Page与自定义Components生命周期

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

Chain of Thought (CoT) 系列论文:大模型思维链,提升 LLM 的推理能力

文章目录 1. COT&#xff1a;Chain of Thought1. 研究背景2. CoT的原理3. CoT Prompt 1. COT&#xff1a;Chain of Thought COT 是 2022.01 由 google 提出的针对提升 LLM 的推理能力的 Prompt Engineering 方法。 paper&#xff1a; Chain-of-Thought Prompting Elicits Re…...

已解决:java.net.BindException: 地址已在使用

1. 问题描述 java.net.BindException: 地址已在使用 是一种常见的网络异常&#xff0c;通常在服务器程序尝试绑定到一个已经被占用的端口或地址时出现。具体的异常信息可能如下&#xff1a; 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介绍&#xff1a; STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ARM的含义&#xff1a; 公司名称&#xff1a;ARM公司成立于1990年&#xff0c;全称是Advanced RISC Machines&#xff08;RISC:Reduced Instruction Set Computer 精简指令集计算机 相对应有C…...

Nginx:高效HTTP服务器与反向代理

Nginx&#xff1a;高效HTTP服务器与反向代理 1、核心特点2、应用场景 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Nginx&#xff0c;一个开源的HTTP服务器与反向代理工具&#xff0c;因其高性能、低资源消耗而备受推崇。以下是Nginx的几…...

vue3二次封装element-puls

将表单的通用信息给设置出来 如: label 的提示信息 , type 的类型 // 定义表单的配置项 const formConfig{ formItems:[ { type:"input", label:"用户ID", placeholder:"请输入用户ID" } ] } 页面配置如 <template v-for"(it…...

在CentOS 7上安装Apache Tomcat 8的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 Apache Tomcat 是一个用于提供 Java 应用程序的 Web 服务器和 Servlet 容器。Tomcat 是由 Apache 软件基金会发布的 Java Servlet…...

深入理解分布式事务中的三阶段提交(3PC),什么是3PC,3PC原理是怎样?3PC的优化?

在上一篇文章中&#xff0c;我们详细介绍了分布式事务中的两阶段提交&#xff0c;以及知道了两阶段提交存在一定的问题 深入理解分布式事务中的两阶段提交&#xff08;2PC&#xff09;&#xff0c;什么是2PC&#xff0c;2PC原理是怎样&#xff1f;2PC有没有什么问题&#xff1…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...