Stream流详解
当我们对一个集合中的元素进行多次过滤应该怎样做?
下面看一个案例
-
按照下面的要求完成集合的创建和遍历
-
创建一个集合,存储多个字符串元素
-
把集合中所有以"张"开头的元素存储到一个新的集合
-
把"张"开头的集合中的长度为3的元素存储到一个新的集合
-
遍历上一步得到的集合
-
-
原始方式示例代码
public class MyStream1 {public static void main(String[] args) {//集合的批量添加ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));//list.add()//遍历list1把以张开头的元素添加到list2中。ArrayList<String> list2 = new ArrayList<>();for (String s : list1) {if(s.startsWith("张")){list2.add(s);}}//遍历list2集合,把其中长度为3的元素,再添加到list3中。ArrayList<String> list3 = new ArrayList<>();for (String s : list2) {if(s.length() == 3){list3.add(s);}}for (String s : list3) {System.out.println(s);} }
}
-
使用Stream流示例代码
public class test1 {public static void main(String[] args) {//集合的批量添加ArrayList<String> list1 = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));//Stream流list1.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));}
}
由此可见
Java Stream流的好处体现在以下几个方面:
- 简化代码:Stream API允许开发者通过声明性方式处理数据,这意味着可以通过更少的代码实现相同的功能,从而提高代码的简洁性和可读性。
- 提高可维护性:由于Stream流的代码更加简洁,因此也更容易维护。当业务逻辑复杂时,使用Stream可以减少出错的机会,并且使得代码更加清晰。
- 函数式编程:Stream流基于函数式编程的思想,这使得它能够很好地支持抽象思维和函数式操作,有助于解决复杂的业务逻辑问题。
- 性能优化:Stream API设计时就考虑到了性能因素,它在内部进行了优化,比如延迟执行和短路操作等,可以在不修改代码的情况下享受性能提升的好处。
- 避免显式数据存储:Stream流不是一种数据结构,它不需要显式地存储数据,而是对数据进行加工和处理,这有助于减少内存的使用。
- 流水线操作:Stream流的处理方式类似于工厂的生产线,每个操作都是流水线上的一个工序,这样的设计使得数据处理流程更加清晰和高效。
- 避免手动管理线程:在使用Stream进行并行处理时,开发者不需要手动管理线程,Stream API会负责这部分工作,这样可以更加专注于业务逻辑本身。
- 易于并行化:Stream流可以很容易地将顺序流转换为并行流,从而利用多核处理器的优势,提高数据处理的速度。
- 强大的操作:Stream API提供了丰富的操作,如过滤、映射、排序等,这些操作可以组合起来形成强大的数据处理链。
- 灵活的数据源:Stream流不仅可以从集合创建,还可以从数组、I/O通道等多种数据源创建,这为数据处理提供了极大的灵活性。
总的来说,Java Stream流通过提供一种高效、简洁、易于维护的方式来处理数据,极大地提升了开发效率和程序的性能。
Stream流的三类方法
-
获取Stream流
-
创建一条流水线,并把数据放到流水线上准备进行操作
-
-
中间方法
-
流水线上的操作
-
一次操作完毕之后,还可以继续进行其他操作
-
-
终结方法
-
一个Stream流只能有一个终结方法
-
是流水线上的最后一个操作
-
生成Stream流的方式
-
Collection体系集合
使用默认方法stream()生成流, default Stream<E> stream()
-
public class test5 {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};//获取stream流Arrays.stream(arr).forEach(s -> System.out.println(s));} } -
Map体系集合
把Map转成Set集合,间接的生成流
-
public class test3 {public static void main(String[] args) {//双列集合//1.创建双列集合HashMap<String,Integer> hm = new HashMap<>();//添加数据hm.put("aaa",111);hm.put("bbb",111);hm.put("ccc",111);hm.put("ddd",111);//3.第一种获取Stream流hm.keySet().stream().forEach(s -> System.out.println(s));//3.第二种获取Stream流hm.entrySet().stream().forEach(s -> System.out.println(s));} } -
数组
通过Arrays中的静态方法stream生成流
-
public class test2 {public static void main(String[] args) {//单列集合获取Stream流ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"a","b","c","d");list.stream().forEach(s -> System.out.println(s));} } -
同种数据类型的多个数据
通过Stream接口的静态方法of(T... values)生成流
-
public class test4 {public static void main(String[] args) {Stream.of(1,2,3,4,5).forEach(s -> System.out.println(s));} }
-
-
Stream流中间操作方法
-
概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
-
常见方法
| 方法名 | 说明 |
|---|---|
| Stream<T> filter(Predicate predicate) | 用于对流中的数据进行过滤 |
| Stream<T> limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据 |
| Stream<T> skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
| static <T> Stream<T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
| Stream<T> distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流 |
public class MyStream3 {public static void main(String[] args) {
// Stream<T> filter(Predicate predicate):过滤
// Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值ArrayList<String> list = new ArrayList<>();list.add("张三丰");list.add("张无忌");list.add("张翠山");list.add("王二麻子");list.add("张良");list.add("谢广坤");//filter方法获取流中的 每一个数据.//而test方法中的s,就依次表示流中的每一个数据.//我们只要在test方法中对s进行判断就可以了.//如果判断的结果为true,则当前的数据留下//如果判断的结果为false,则当前数据就不要.
// list.stream().filter(
// new Predicate<String>() {
// @Override
// public boolean test(String s) {
// boolean result = s.startsWith("张");
// return result;
// }
// }
// ).forEach(s-> System.out.println(s));//因为Predicate接口中只有一个抽象方法test//所以我们可以使用lambda表达式来简化
// list.stream().filter(
// (String s)->{
// boolean result = s.startsWith("张");
// return result;
// }
// ).forEach(s-> System.out.println(s));list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));}
}
limit&skip代码演示
public class StreamDemo02 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前3个数据在控制台输出list.stream().limit(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求2:跳过3个元素,把剩下的元素在控制台输出list.stream().skip(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));}
}
concat&distinct代码演示
public class StreamDemo03 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前4个数据组成一个流Stream<String> s1 = list.stream().limit(4);//需求2:跳过2个数据组成一个流Stream<String> s2 = list.stream().skip(2);//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
// Stream.concat(s1,s2).forEach(s-> System.out.println(s));//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));}
}
public class test6 {public static void main(String[] args) {/*map 转换流中的数据类型注意点1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意点2: 修改Stream流中的数据,不会影响原来集合或者数组中的数据*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"张三-15","李四-16");//需求: 只获取里面的年龄并进行打印//String -> int//第一个类型: 流中原来的数据类型//第二个类型: 要转成之后的数据list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {String[] arr = s.split("-");String ageString = arr[1];int age = Integer.parseInt(ageString);return age;}}).forEach(s -> System.out.println(s));list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));}
}
Stream流终结操作方法
-
概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
-
常见方法
方法名 说明 void forEach(Consumer action) 对此流的每个元素执行操作 long count() 返回此流中的元素数
Stream流的收集操作
-
概念
对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
-
常用方法
方法名 说明 R collect(Collector collector) 把结果收集到集合中 -
工具类Collectors提供了具体的收集方式
| 方法名 | 说明 |
|---|---|
| public static <T> Collector toList() | 把元素收集到List集合中 |
| public static <T> Collector toSet() | 把元素收集到Set集合中 |
| public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
public class StreamTest5 {// toList和toSet方法演示public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();for (int i = 1; i <= 10; i++) {list1.add(i);}list1.add(10);list1.add(10);list1.add(10);list1.add(10);list1.add(10);//filter负责过滤数据的.//collect负责收集数据.//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.List<Integer> list = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());System.out.println(list);Set<Integer> set = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());System.out.println(set);}
}
public class StreamTest6 {public static void main(String[] args) {/*Stream流的收集方法 toMap方法演示创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄"zhangsan,23""lisi,24""wangwu,25"保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值*/ArrayList<String> list = new ArrayList<>();list.add("zhangsan,23");list.add("lisi,24");list.add("wangwu,25");Map<String, Integer> map = list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;}// collect方法只能获取到流中剩余的每一个数据.//在底层不能创建容器,也不能把数据添加到容器当中).collect(Collectors.toMap(s -> s.split(",")[0],s -> Integer.parseInt(s.split(",")[1])));System.out.println(map);}}
案例来源:
//https://www.bilibili.com/video/BV17F411T7Ao/?spm_id_from=333.337.search-card.all.click
相关文章:
Stream流详解
当我们对一个集合中的元素进行多次过滤应该怎样做? 下面看一个案例 按照下面的要求完成集合的创建和遍历 创建一个集合,存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新…...
javaweb学习(day05-TomCat)
一、介绍 1 官方文档 地址: https://tomcat.apache.org/tomcat-8.0-doc/ 2 WEB 开发介绍 2.1 WEB 在英语中 web 表示网/网络资源(页面,图片,css,js)意思,它用于表示 WEB 服务器(主机)供浏览器访问的资源 2.2 Web 资源 WEB 服务器 ( 主机 ) 上供外界访问的 …...
【Unity】构建简单实用的年份选择器(简单原理示范)
在许多应用程序和游戏中,年份选择是一个常见的需求。无论是在日历应用程序中查看事件,还是在历史类游戏中选择时间段,年份选择器都是用户体验的重要组成部分,下面实现一个简易的年份选择器。 一、效果预览: 目录 一、…...
LeetCode 2120.执行所有后缀指令
现有一个 n x n 大小的网格,左上角单元格坐标 (0, 0) ,右下角单元格坐标 (n - 1, n - 1) 。给你整数 n 和一个整数数组 startPos ,其中 startPos [startrow, startcol] 表示机器人最开始在坐标为 (startrow, startcol) 的单元格上。 另给你…...
租赁小程序|租赁系统|租赁软件开发带来高效运营
随着社会的不断发展和科技的不断进步,越来越多的企业开始关注设备租赁业务。设备租赁作为一种短期使用设备的方式,为企业提供了灵活和成本节约的优势。针对设备租赁业务的管理和提升企业竞争力的需求,很多企业选择定制开发设备租赁系统。本文…...
大数据集群管理软件 CDH、Ambari、DataSophon 对比
文章目录 引言工具介绍CDHAmbariDataSophon 对比分析 引言 大数据集群管理方式分为手工方式和工具方式,手工方式一般指的是手动维护平台各个组件,工具方式是靠大数据集群管理软件对集群进行管理维护。本文针对于常见的方法和工具进行比较,帮助…...
插值、逼近、拟合、光顺
插值 插值(Interpolation)是数学和计算科学中的一个重要概念,它指的是通过已知的一系列数据点,构造一个函数或曲线,并据此估计未知数据点的值。这个过程通常发生在已知数据点之间,用于预测或估算在这些已知…...
Java单元测试 - mock静态方法
文章目录 1. mock 静态方法2. 升级 maven 依赖3. 示例 1. mock 静态方法 mockito 在 3.4.0 版本之后,开始支持 mock static method。 2. 升级 maven 依赖 <dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artif…...
Unity使用PlayableAPI 动态播放动画
1.初始化animator,创建Playable图,创建动画Playable private void InitAnimator(GameObject headGo) {if (headGo){_headAnimator headGo.GetComponent<Animator>();if (_headAnimator){_headAnimator.cullingMode AnimatorCullingMode.AlwaysA…...
unity使用Registry类将指定内容写入注册表
遇到一个新需求,在exe执行初期把指定内容写入注册表,Playerprefs固然可以写入,但是小白不知道怎么利用Playerprefs写入DWORD类型的数据,因此使用了Registry类 一. 对注册表中键的访问 注册表中共可分为五类 一般在操作时&#…...
Python进阶学习:Pandas--将一种的数据类型转换为另一种类型(astype())
Python进阶学习:Pandas–将一种的数据类型转换为另一种类型(astype()) 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&…...
OpenCV开发笔记(七十五):相机标定矫正中使用remap重映射进行畸变矫正
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/136293833 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究 红胖子(红模仿…...
光伏预测 | Matlab基于CNN-SE-Attention-ITCN的多特征变量光伏预测
光伏预测 | Matlab基于CNN-SE-Attention-ITCN的多特征变量光伏预测 目录 光伏预测 | Matlab基于CNN-SE-Attention-ITCN的多特征变量光伏预测预测效果基本描述模型简介程序设计参考资料 预测效果 基本描述 Matlab基于CNN-SE-Attention-ITCN的多特征变量光伏预测 运行环境: Matla…...
k8s学习笔记-基础概念
(作者:陈玓玏) deployment特别的地方在于replica和selector,docker根据镜像起容器,pod控制容器,job、cronjob、deployment控制pod,job做离线任务,pod大多一次性的,cronj…...
C语言 变量
变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。 变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头…...
2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui·增加心率计算器·退休储蓄计算·贷款还款计算器等数接口
2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui增加心率计算器退休储蓄计算贷款还款计算器等数接口 更新日志 前言:本次更新中途跨越了很多个版本,其次本次ui大改版-同步实时发布教程《带9.7k预算的实战项目layuiph…...
WEB漏洞 逻辑越权之支付数据篡改安全
水平越权 概述:攻击者尝试访问与他拥有相同权限的用户的资源 测试方法:能否通过A用户操作影响到B用户 案例:pikachu-本地水平垂直越权演示-漏洞成因 1)可以看到kobe很多的敏感信息 2)burp抓包,更改user…...
45、WEB攻防——通用漏洞PHP反序列化POP链构造魔术方法原生类
文章目录 序列化:将java、php等代码中的对象转化为数组或字符串等格式。代表函数serialize(),将一个对象转换成一个字符;反序列化:将数组或字符串等格式还成对象。代表函数unserialize(),将字符串还原成一个对象。 P…...
雾锁王国服务器怎么建?雾锁王国服务器搭建方法
雾锁王国Enshrouded服务器搭建怎么搭建?非常简单,阿里云计算巢雾锁王国程序,可以一键搭建雾锁王国多人联机服务器,腾讯云是基于雾锁王国镜像系统,阿里云服务网aliyunfuwuqi.com汇总雾锁王国服务器搭建,超简…...
设计模式篇---观察者模式
文章目录 概念结构实例总结 概念 观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其他相关依赖对象都得到通知并被自动更新。 观察者模式是使用频率较高的一个模式,它建立了对象与对象之间的依赖…...
Spotify广告拦截终极方案:BlockTheSpot深度技术解析与实战指南
Spotify广告拦截终极方案:BlockTheSpot深度技术解析与实战指南 【免费下载链接】BlockTheSpot Video, audio & banner adblock/skip for Spotify 项目地址: https://gitcode.com/gh_mirrors/bl/BlockTheSpot 在享受Spotify免费音乐服务时,无休…...
用PyTorch从零实现DQN算法:以CartPole游戏为例(附完整代码)
用PyTorch从零实现DQN算法:以CartPole游戏为例(附完整代码) 在强化学习领域,深度Q网络(DQN)算法无疑是一座重要的里程碑。它将深度学习的强大表征能力与强化学习的决策框架完美结合,为解决复杂环…...
深度解密Jsxer:JSXBIN反编译器的技术原理与工程实现
深度解密Jsxer:JSXBIN反编译器的技术原理与工程实现 【免费下载链接】jsxer A fast and accurate JSXBIN decompiler. 项目地址: https://gitcode.com/gh_mirrors/js/jsxer 在Adobe创意套件生态中,ExtendScript二进制格式(JSXBIN&…...
PEG-PLLA-Mal-Fe₃O₄ NPs,聚乙二醇-聚L-乳酸-马来酰亚胺修饰四氧化三铁纳米颗粒,定义与特点
PEG-PLLA-Mal-Fe₃O₄ NPs,聚乙二醇-聚L-乳酸-马来酰亚胺修饰四氧化三铁纳米颗粒,定义与特点PEG-PLLA-Mal-Fe₃O₄ NPs是一类以四氧化三铁(Fe₃O₄)纳米颗粒为核心,并在其表面引入聚乙二醇-聚L-乳酸(PEG-PL…...
通过Citrix API实现许可证管理自动化与系统集成
经过Citrix API实现许可证管理自动化跟系统集成掏心窝子说,我就是个“许可证焦虑”的过来人。以前项目上线前晚上,最怕的就是看到“License不足”的警告。那时候,不可你要这么说,得跟产品经理、业务部门扯皮还得临时协调资源&…...
代码随想录算法训练营第二天|leetcode209 长度最小的子数组 leetcode59 螺旋矩阵Ⅱ 58. 区间和
209. 长度最小的子数组 题目链接:209. 长度最小的子数组 - 力扣(LeetCode) 解题思路:利用快慢指针slow,fast进行区间的划分。最外层循环每次开始时都将fast进入到区间之中,当sum>target时,…...
MATLAB 2020b 中文版安装避坑指南:断网、杀软、中文路径,一个都不能错
MATLAB 2020b 中文版安装避坑指南:断网、杀软、中文路径,一个都不能错 每次打开MATLAB都卡在启动界面?安装进度条走到99%就再也不动了?这些让人抓狂的问题,很可能是因为忽略了几个关键安装细节。作为一款功能强大的数学…...
从MATLAB到Tecplot:手把手教你搞定复杂非结构网格(含FEPolygon/FEPolyhedron)的数据转换
从MATLAB到Tecplot:复杂非结构网格数据转换的工程实践指南 在工程仿真和科学计算领域,数据可视化是理解复杂现象的关键环节。MATLAB作为强大的数值计算工具,常被用于生成各类仿真数据,而Tecplot则是专业工程师首选的科学可视化软件…...
手把手教你用Xilinx Artix-7和MT41J256M16RH-125:E配置MIG IP核(避坑指南)
从芯片手册到MIG配置:Artix-7与DDR3硬件设计实战解析 当FPGA开发者第一次面对DDR3内存接口设计时,数据手册里密密麻麻的参数表格和Vivado中复杂的MIG配置界面往往让人望而生畏。本文将以美光MT41J256M16RH-125:E内存芯片与Xilinx Artix-7系列FPGA的组合为…...
从零复现RetinaNet:PyTorch环境搭建与COCO数据集实战避坑指南
1. 环境准备:从零搭建PyTorch开发环境 在Windows系统上搭建PyTorch环境就像组装一台新电脑——选对配件才能避免后续的兼容性问题。我建议使用Anaconda作为基础环境管理器,它能有效隔离不同项目的依赖关系。下面是我反复验证过的安装流程: 首…...
