【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.使用终结方法处理数据

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/402275.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[C++][opencv]基于opencv实现photoshop算法灰度化图像

测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 BlackWhite.hpp #ifndef OPENCV2_PS_BLACKWHITE_HPP_ #define OPENCV2_PS_BLACKWHITE_HPP_#include "opencv2/core.hpp"namespace cv {class BlackWhite { public:float red; //红色的灰度系…

阿里云ubuntu系统安装mysql8.0

一、安装mysql8.0 1.已安装其他版本的mysql&#xff0c;需要删除 若没有不需要此操作 1 #卸载MySQL5.7版本 2 apt remove -y mysql-client5.7* mysql-community-server5.7* 4 # 卸载5.7的仓库信息 5 dpkg-l | grep mysql | awk iprint $2} | xargs dpkg -P2.更新仓库 apt u…

Python酷库之旅-第三方库Pandas(084)

目录 一、用法精讲 351、pandas.Series.str.isdigit方法 351-1、语法 351-2、参数 351-3、功能 351-4、返回值 351-5、说明 351-6、用法 351-6-1、数据准备 351-6-2、代码示例 351-6-3、结果输出 352、pandas.Series.str.isspace方法 352-1、语法 352-2、参数 3…

0815,析构函数,拷贝构造函数,赋值运算符函数

来自同济医院的问候 目录 01&#xff1a;对象创建 001.cc 003size.cc 02&#xff1a;对象销毁 004pointer.cc 005destroytime.cc 03&#xff1a;本类型对象的复制 3.1 拷贝构造函数 006cp.cc 007cptime.cc 008recursion.cc 009rightleft.cc 3.2 赋值运算符函数 …

平安城市/雪亮工程现状及需求分析:EasyCVR视频汇聚平台助力雪亮工程项目建设

一、背景现状 经过近几年的努力&#xff0c;平安城市雪亮工程建设取得了显著的成绩&#xff0c;完成了前端高清视频点位和高清卡口系统建设&#xff0c;建成了&#xff08;视频监控类&#xff09;、&#xff08;卡口类&#xff09;和&#xff08;应用类&#xff09;的平台。这…

BvSP_ Broad-view Soft Prompting for Few-Shot Aspect Sentiment Quad Prediction

中文题目: 英文题目: BvSP: Broad-view Soft Prompting for Few-Shot Aspect Sentiment Quad Prediction 论文地址: aclanthology.org/2024.acl-long.460.pdf 代码地址: https://github.com/byinhao/BvSP 论文级别&#xff0c; 单位: (2024 ACL long paper) 南开大学&#xff0…

Fortify三种扫描模式有什么区别?分别怎么用?

一、通过“Audit Workbench”进行测试 “Audit Workbench”支持Java语言源代码的测试。 二、通过“Scan Wizard”进行测试 “Scan Wizard”支持Java、Python、C/C、.Net、Go、PHP、Flex、Action Script、HTML、XML、JavaScript、TypeScript、Kotlin、SQL、ABAP、ColdFusion语言…

RCE编码绕过--php://filter妙用

目录 代码 如何绕过 payload构造 代码 <?php $content <?php exit; ?>; $content . $_POST[txt]; file_put_contents($_POST[filename],$content); 当你想要输入代码的时候前面会有<?php exit;?>;&#xff0c;代码没有办法执行下去&#xff0c;所以…

2024新型数字政府综合解决方案(三)

新型数字政府综合解决方案通过融合人工智能、大数据和云计算技术&#xff0c;建立了一个智能化、互联互通的政府服务平台&#xff0c;旨在提升政府服务效率与透明度。该方案通过全面数字化政务流程&#xff0c;实现数据的实时共享和自动化处理&#xff0c;使公众能够便捷地访问…

基于小土堆入门教程的pytorch训练神经网络方法实现

成果展示 在学习吴恩达机器学习和小土堆入门教程的基础上&#xff0c;完成了该实验&#xff0c;目前可以实现标准数据集的加载、网络模型的搭建及训练、数据可视化、GPU加速功能&#xff0c;是机器学习理论的初步实践 import torch import torchvision.datasets from torch i…

安卓应用开发学习:查看手机传感器信息

一、引言 在手机app的开发中经常会用到手机的传感器&#xff0c;在《Android App 开发进阶与项目实战》一书的第10章就介绍了传感器的一些功能和用法。要想使用传感器&#xff0c;首先得知道手机具备哪些传感器。书中有传感器类型取值的说明&#xff0c;并提供了一个查看手机传…

聊聊场景及场景测试

在我们进行测试过程中&#xff0c;有一种黑盒测试叫场景测试&#xff0c;我们完全是从用户的角度去理解系统&#xff0c;从而可以挖掘用户的隐含需求。 场景是指用户会使用这个系统来完成预定目标的所有情况的集合。 场景本身也代表了用户的需求&#xff0c;所以我们可以认为…

橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码

源码名称&#xff1a;酷黑简洁大气体育直播自适应模板赛事直播门户网站 源码开发环境&#xff1a;帝国cms 7.5 安装环境&#xff1a;phpmysql 带采集&#xff0c;可以挂着电脑上自动采集发布&#xff0c;无需人工操作&#xff01; 橙色简洁大气体育直播自适应模板赛事直播门户…

Java Web|day5.MyBatis

MyBatis 定义 它是一款半自动的ORM持久层框架&#xff0c;具有较高的SQL灵活性&#xff0c;支持高级映射(一对一&#xff0c;一对多)&#xff0c;动态SQL&#xff0c;延迟加载和缓存等特性&#xff0c;但它的数据库无关性较低 **ORM: **Object Relation Mapping&#xff0c;…

数字孪生技术框架:从数据到决策的桥梁

随着科技的飞速发展&#xff0c;数字孪生技术作为一种创新的信息化手段&#xff0c;正逐步渗透到各个行业领域&#xff0c;成为推动数字化转型的重要力量。数字孪生技术框架&#xff0c;作为支撑这一技术体系的核心架构&#xff0c;以其独特的层级结构&#xff0c;实现了从数据…

如何选择适合流水线作业的工业级条码读码器

高度自动化的工业生产环境中&#xff0c;条码二维码的应用&#xff0c;在工厂流水线作业的高效性和准确性对于企业的生产效率和质量管控至关重要&#xff0c;条码二维码扫描设备作为流水线中用于读取条码或二维码朔源信息的关键设备&#xff0c;它们能够快速、准确地识别和采集…

vim - vim模式及部分操作

文章目录 一、vim 基本介绍二、vim 的简单使用三、几种常用模式切换四、命令模式和底行模式的操作汇总 一、vim 基本介绍 vim 是一款多模式的编辑器。vim 中有很多子命令来进行代码的编写操作。 同时&#xff0c;vim 提供了不同的模式供我们选择。 在vim下的底行模式下通过:he…

8.15 day bug

bug1 一个按钮折腾了 两个小时 一直点第一个按钮&#xff0c;然后进去后发现根本没有课程&#xff0c;需要创建workspace&#xff0c;然后各种问题&#xff0c;还是没把课程启动起来&#xff0c;然后去看gitpod使用文档&#xff0c;搞懂工作区到底是怎么回事&#xff0c;一通操…

JVM 有哪些垃圾回收算法(回收机制)?

JVM 有哪些垃圾回收算法&#xff08;回收机制&#xff09;&#xff1f; 标记-清除算法 在Java虚拟机中&#xff0c;标记-清除算法是一种用于垃圾回收的算法。它分为两个阶段&#xff1a;标记阶段和清除阶段。 在标记阶段&#xff0c;垃圾收集器会遍历堆内存中的所有对象&…

JavaEE 第11节 定时器

前言 本篇博客重点介绍定时器的简单实现&#xff0c;帮助理解其底层原理。关于JAVA工具类自带的定时器&#xff0c;只会简单介绍&#xff0c;详细使用参阅官方文档&#xff08;下文中有官方文档的连接&#xff09;。 一、什么是定时器 定时器的概念非常简单。 它在软件开发…