Java Stream 编程

news2025/2/1 6:08:20

Java Stream 编程

教程:https://www.bilibili.com/video/BV1te411w722

1. 不可变集合

1.1 不可变集合应用场景

元数据,只允许查询的数据集合

1.2 创建不可变集合

List、Set、Map 接口中的静态方法 of()

List<String> list = List.of("张三", "李四", "王五");

Set<String> set = Set.of("A", "B", "C");

Map<String, String> map = Map.of("k1", "v1", "k2", "v2");

对不可变集合进行修改时会报错:

在这里插入图片描述

Note:
当创建不可变 Set 或者 Map 时,不能有重复的元素和相同的 Key
Map 里面的 of 参数有上限,最多 10 个键值对!(因为一个函数不能有多个可变参数)

由于 Mapof 方法最多只能有 10 个键值对,引入 ofEntries 方法和 copyOf

1.2.1 Map.ofEntries 方法

Map<String, String> map = Map.ofEntries(
               Map.entry("k1", "v1"),
               Map.entry("k2", "v2"),
               Map.entry("k3", "v3"),
               Map.entry("k4", "v4"));
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("mary", 1);
hashMap.put("jack", 2);
hashMap.put("mike", 3);
// toArray 方法在底层会比较集合的长度和数组的长度两者的大小
// 若集合长度 > 数组的长度,数组在数组中放不下,此时会根据实际数据的个数重新创建数组
// 若集合长度 <= 数组的长度,数据在数组中放得下,此时不会创建新的数组,而是直接使用
Map<String, Integer> entries = Map.ofEntries(hashMap.entrySet().toArray(new Map.Entry[0]));
entries.forEach((k, v) -> System.out.println(k + ":" + v));

1.2.2 Map.copyOf 方法(JDK 10)

Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("mary", 1);
hashMap.put("jack", 2);
hashMap.put("mike", 3);
Map.copyOf(hashMap)

2. Stream 流

2.1 小需求

在这里插入图片描述

List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");

list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(System.out::println);

2.2 Stream 的思想

把要操作的步骤放在一个流水线上

2.3 Stream 的作用

结合 Lambda 表达式,简化集合、数组的操作

2.4 Stream 的使用步骤

  1. 先得到一条 Stream,并把数据放上去
  2. 利用 Stream 中的 API 进行各种操作(中间方法和终结方法)

2.4.1 获取 Stream

在这里插入图片描述

// 1. 单列集合
List<String> list = new ArrayList<>();
Collections.addAll(list, "A", "B", "C", "D");
list.stream().forEach(System.out::println);

// 2. 双列集合
Map<String, Integer> map = new HashMap<>();
map.put("Mary", 1);
map.put("Mike", 2);
map.put("Jack", 3);
map.put("Rose", 4);
map.entrySet().stream().forEach(System.out::println);
map.forEach((k, v) -> System.out.println(k + " <=> " + v));

// 3. 数组
int[] arr = {1, 2, 3, 4};
Arrays.stream(arr).forEach(System.out::println);

// 4. 零散数据
Stream.of("Hello", 111, "World").forEach(System.out::println);

Note:
Stream.of 方法使用细节,方法的参数可以传递数组,但是数组必须是引用类型,若传递基本数据类型的数组会把整个数组当作一个元素放在 stream 中。

2.4.2 Stream 的中间方法

在这里插入图片描述

Note:

  • 中间方法会返回新的 Stream 流,原来的 Stream 流只能使用一次,建议使用链式编程
  • 修改 Stream 中的数据,不会影响原来集合或者数组中的数据
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
Stream<String> stream1 = list.stream();
Stream<String> stream2 = stream1.filter(name -> name.startsWith("张"));
Stream<String> stream3 = stream1.filter(name -> name.length() == 3);

在这里插入图片描述

2.4.2.1 filter 过滤

使用过滤条件

2.4.2.2 skip 跳过 / limit 取前几个

skip 表示跳过几个元素,limit 表示取前几个元素:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
list.stream().skip(2).limit(2).forEach(System.out::println);

在这里插入图片描述

2.4.2.3 distinct 去重
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "张无忌", "张无忌", "周芷若", "周芷若", "赵敏", "张强", "张三丰");
list.stream().distinct().forEach(log::info);

在这里插入图片描述

底层使用了 HashSet,因此依赖 hashCodeequals 方法。

2.4.2.4 concat 合并
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");

List<String> list2 = new ArrayList<>();
Collections.addAll(list2, "白眉鹰王", "金毛狮王");

Stream.concat(list.stream(), list2.stream()).forEach(log::info);

在这里插入图片描述

2.4.2.5 map 转换数据类型
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-14", "周芷若-13", "赵敏-13", "张强-20", "张三丰-100");
list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> log.info("{}", s));

在这里插入图片描述

2.4.3 Stream 的终结方法

在这里插入图片描述

2.4.3.1 forEach 遍历

遍历元素

2.4.3.2 count 统计
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
log.info("{}", list.stream().count());
log.info("{}", list.stream().filter(name -> name.startsWith("张")).count());

在这里插入图片描述

2.4.3.3 toArray 转换为数组
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// 这里面的 value 表示数组长度, 默认已经得到了
String[] arr = list.stream().toArray(value -> new String[value]);
//        String[] arr = list.stream().toArray(String[]::new);
log.info(Arrays.toString(arr));

在这里插入图片描述

Note:
空参 toArray 方法会默认使用数组 Object[]

2.4.3.4 collect 收集为集合

转换为 List 集合:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
List<String> newList = list.stream()
        .filter(s -> "男".equals(s.split("-")[1]))
        .collect(Collectors.toList());
newList.forEach(log::info);

//        List<String> newList = list.stream()
//                .filter(s -> "男".equals(s.split("-")[1])).toList();

在这里插入图片描述

转换为 Set 集合:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
Set<String> set = list.stream()
        .filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());
log.info(set.toString());

在这里插入图片描述

转换为 Map(注意 key 不能重复):

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
Map<String, Integer> map = list.stream()
        .filter(s -> "男".equals(s.split("-")[1]))
        .collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));
map.forEach((k, v) -> log.info("{} <=> {}", k, v));

在这里插入图片描述

2.5 Stream 排序

2.5.1 Map 排序

Map<String, String> map = Map.ofEntries(
                Map.entry("Mary", "15"),
                Map.entry("Amy", "16"),
                Map.entry("Jack", "13"),
                Map.entry("Rose", "14"));
                
// 根据 key 正序排序
map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(System.out::println);

// 根据 value 正序排序
map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);

// 根据 key 倒序排序
map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByKey())).forEach(System.out::println);

// 根据 value 倒序排序
map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).forEach(System.out::println);

2.5.2 List 排序

Random random = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
    list.add(random.nextInt(100));
}

// 默认正序
list.stream().sorted().forEach(System.out::println);
// 倒序
list.stream().sorted((o1, o2) -> o2 - o1).forEach(System.out::println);

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud 2021版本教程:使用nacos作为注册中心和配置中心(2021版本+Boot2.7.6)

目录 前言 系列文章目录 一、什么是Nacos 1、nacos架构原理 2、nacos、eureka、zookeeper的区别 1、参考博客&#xff0c;写得很详细通俗易懂&#xff1a;一文说清eureka、zookepeer、nacos三者的关系 - 知乎 2、三者区别&#xff1a; 3、CAP原理&#xff1a; 二、项目…

MyBatis八股文

1、什么是MyBatis框架&#xff1f; MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射&#xff0c;它内部封装了jdbc&#xff0c;不需要我们再写JDBC连接、使开发者只需要关注sql语句本身和业务&#xff0c;而不需要花费精力去处理加载驱动、…

【数据结构】基础:常见排序算法

【数据结构】基础&#xff1a;常见排序算法 摘要&#xff1a;本文将从排序的概念及其附属概念出发&#xff0c;再对排序算法进行分类&#xff0c;并对其思想与实现进行说明&#xff0c;最后对各个算法进行总结。 文章目录【数据结构】基础&#xff1a;常见排序算法一. 排序的概…

K8s CRD 和 Operator 来进行 NebulaGraph 的部署

中间件及运维管理 我们基于 K8s CRD 和 Operator 来进行 NebulaGraph 的部署&#xff0c;同时通过服务集成到现有的部署配置页面和运维管理页面&#xff0c;来获得对 Pod 的执行和迁移的控制能力。基于 sidecar 模式监控、收集 NebulaGraph 的核心指标并通过 Telegraf 发送到携…

【第十四章 错误日志,二进制日志,查询日志,慢查询日志】

第十四章 第十四章 错误日志&#xff0c;二进制日志&#xff0c;查询日志&#xff0c;慢查询日志 1.错误日志&#xff1a; ①错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息…

Servlet还不会?那就看这篇文章吧

一. Servlet是什么? Servlet是Server Applet的简称&#xff0c;也就是服务程序。当然&#xff0c;杨哥习惯称它为"服务连接器"。 像上面这么说&#xff0c;大家可能会有所疑惑&#xff1a;什么是服务程序&#xff1f;可能有些人对这个还是不太懂&#xff0c;那么接下…

我国汽车配件行业需求空间较大 国产品牌配件市场份额逐渐提升

根据观研报告网发布的《2022年中国汽车配件行业分析报告-行业全景调研与发展战略咨询》显示&#xff0c;根据Markline全球汽车信息平台统计&#xff0c;2020年&#xff0c;全球整车市场产量规模约为7769.80万辆。对于整车厂而言&#xff0c;在委托上游制造商按照要求供应零部件…

软文营销对企业品牌推广的好处有哪些?

众所周知&#xff0c;互联网改变了我们的生活&#xff0c;他的横空出世一度改变我们的工作模式&#xff0c;又跟我们生活息息相关。如今&#xff0c;随着网络的深入发展&#xff0c;网络对企业的营销模式也产生了巨大的改变。其中网络软文营销成为了当下众多企业的主要营销手段…

Web漏洞扫描-Appscan安装配置及扫描

软件介绍 AppScan 是一种 Web 应用程序安全扫描工具&#xff0c;可帮助组织识别和修复其 Web 应用程序中的漏洞。它结合使用自动和手动测试技术来识别漏洞&#xff0c;例如跨站点脚本 (XSS)、SQL 注入和不安全的文件上传等。 AppScan 可用于在开发生命周期的不同阶段扫描 Web…

Unity 摄像机

摄像机分为两种 &#xff08;1&#xff09;透视摄像机 &#xff08;2&#xff09; 正交摄像机 一般3D游戏使用的透视多一点&#xff0c;2D游戏使用正交多一点。 相机参数 清除标记&#xff1a; &#xff08;1&#xff09;天空盒 &#xff08;2&#xff09;仅深度&#xff…

Problem J. Prime Game(数学 贡献)[2018-2019 ACM-ICPC, Asia Nanjing Regional Contest]

题目如下&#xff1a; 题解 or 思路 我们可以发现暴力去求解是无法完成的 O(n2)O(n^2)O(n2) 我们可以从贡献出发&#xff0c;计算每一个位置上的质因子所做的贡献 我们可以先通过分解质因子&#xff0c;记录每一个质因子的位置&#xff0c;在这里使用 vectorvectorvector 容器…

力扣(LeetCode)1760. 袋子里最少数目的球(C++/C)

二分查找 直观思维是对每个袋子进行分球操作&#xff0c;这样枚举似乎无从下手。逆向思维&#xff0c;从 111 开始&#xff0c;枚举袋子里球的最大数量&#xff0c;可以计算划分每个袋子需要的最小次数&#xff0c;通过最小次数之和&#xff0c;判断方案是否可行。由于从小到大…

python3安装PIL库的经历

前提&#xff1a;我是在电脑上同时装了python2和python3 两个环境。详见 Windows环境同时安装多个版本的Python解释器&#xff08;python2和python3&#xff09;&#xff08;超详细&#xff09;_落墨画雪的博客-CSDN博客_安装多个版本python 首先&#xff0c;PIL官方版不支持py…

程序员能干到退休吗?写了40年代码的「骨灰级码农」给出了15条建议

寒冬、裁员、降薪、996、秃头、最近几年这些词汇不断在各位码农的周围盘旋。 很多程序员对自己目前的状态干到困惑和焦虑&#xff0c;而且这好像是国内外程序们都会遇到的问题。 最近&#xff0c;在Reddit上&#xff0c;一位干了40年程序员的网友发表了对这一问题的看法&#x…

辛二酰苯胺异羟肟酸/葛根素/黄芩苷β-环糊精(β-CD)环糊精包合物/β环糊精二棕榈脂质体制备

这里给大家分享的科研内容是辛二酰苯胺异羟肟酸/葛根素/黄芩苷β-环糊精(β-CD)环糊精包合物/β环糊精二棕榈脂质体的制备&#xff0c;和小编一起来看&#xff01; 黄芩苷β-环糊精(β-CD)环糊精包合物脂质体制备方法&#xff1a; 采用傅里叶红外变换光谱法(FTIR)确认了黄芩苷…

工控CTF之协议分析4——MQTT

协议分析 流量分析 主要以工控流量和恶意流量为主&#xff0c;难度较低的题目主要考察Wireshark使用和找规律&#xff0c;难度较高的题目主要考察协议定义和特征 简单只能简单得干篇一律&#xff0c;难可以难得五花八门 常见的工控协议有&#xff1a;Modbus、MMS、IEC60870、…

Appium基础 — Chrome Inspect定位工具

1、Chrome Inspect介绍 Chrome Inspect定位工具是用来抓取app中Webview页面的。 为了项目的需求&#xff0c;为了更好的保证效果和布局跨平台&#xff0c;Android&H5混合开发一般是我们不错的选择。Google浏览器中的Chrome Inspect定位工具&#xff0c;提供了一个移动端W…

(六)docker容器数据卷的理解和使用

目录 一、容器数据卷是什么 二、容器数据卷能干吗 三、宿主vs容器之间映射添加容器卷 四、读写规则映射添加说明 五、卷的继承和共享 一、容器数据卷是什么 Docker将运行的环境打包形成容器运行&#xff0c; Docker容器产生的数据&#xff0c;如果不通过docker commit生成…

【软件测试】快速迭代的敏捷项目?测试怎么做?测试人怎么提升自我价值......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 提到敏捷项目时&…

【嵌入式】Linux开发工具arm-linux-gcc安装及使用

知识架构及层次 — 程序编译及调试 嵌入式交叉编译器安装配置 宿主机 执行编译、链接嵌入式软件的计算机 目标机 运行嵌入式软件的硬件平台 “本地”编译器 用来生成在与编译器本身所在的计算机和操作系统&#xff08;平台&#xff09;相同的环境下运行的目标代码&#xff0c…