我们已经学习了 Kotlin 中的空安全(null safety)。在本节中,我们将讨论如何处理集合中的空值(null),因为集合比其他数据类型更复杂。我们还将讨论如何处理可空元素时常用的便利方法。

集合与空值

可空集合和具有可空元素的非空集合是同一枚硬币的两面。此外,我们还需要认识到空集合和可空集合之间的区别。让我们看看四种情况:

val list = listOf<String>()var nullableList: List<Int>? = listOf<Int>(1, 2, 4, 6)val listWithNullableElements: List<Int?> = listOf<Int?>(1, 2, 4, null, null)var absolutelyNullableList: List<Int?>? = listOf<Int?>(1, 2, 4, null, null)

第一种情况:我们有一个简单的空列表。我们可以像对待常规列表一样处理它,并不需要担心空指针异常(NullPointerException)。这个列表是实际的且非空的,只是为空。

第二种情况:我们有一个可空的列表:这样的列表中的元素不可为空,必须是实际的整数。但变量 nullableList 本身可以为空。在使用可空列表时,我们需要使用安全调用运算符(?.)、空值合并运算符(?:)等操作,例如:

val list: List<Int> = nullableList ?: listOf<Int>()

第三种情况:我们有一个具有可空元素的列表。该列表的类型是非空的,但其中的元素可以为空。

val num: Int = listWithNullableElements[1] ?: 150

第四种情况:我们结合了第二种和第三种情况:

val num: Int = absolutelyNullableList?.get(1) ?: 150

基本原则是:如果可以返回一个空集合,最好返回空集合,而不是返回 null,避免使用可空类型。然而,有时我们确实需要处理可空集合。例如,如果我们声明了一个可以接收值或 null 的变量(var 而不是 val),那么 null 就相当于“无元素”,“没有答案”或“没有结果”。

从包含空值的序列创建非空集合

有时你会遇到包含空值的元素序列,而你需要使用这些序列创建一个没有空值的集合。在这种情况下,可以使用特定的函数 listOfNotNull()setOfNotNull(),它们帮助我们删除所有空值并返回默认的只读非空集合。让我们来看一下它是如何工作的:

val list = listOfNotNull(1, null, 50, 404, 42, null, 42, 404) // [1, 50, 404, 42, 42, 404]
val set = setOfNotNull(1, null, 50, 404, 42, null, 42, 404) // [1, 50, 404, 42]

所有空值元素都被从新集合中删除。如果你的元素序列只有空值,这些方法将返回一个空集合(非空!)。记住,如果你需要一个可变集合,可以通过 toMutableList()toMutableSet() 将其转换为可变集合。

可空集合的函数

Kotlin 提供了一些方便的工具来处理具有可空元素的集合:isNullOrEmpty()getOrNull()firstOrNull()lastOrNull()randomOrNull()。让我们来看看它们!

  • isNullOrEmpty():如果集合为空或为 null,则返回 true。否则返回 false
val emptySet: Set<Int>? = setOf()
val nullSet: Set<Int>? = null
val set = setOf<Int?>(null, null)println(emptySet.isNullOrEmpty()) // true,因为集合为空
println(nullSet.isNullOrEmpty()) // true,因为集合为 null
println(set.isNullOrEmpty()) // false,因为集合中有两个空值元素
  • getOrNull():返回列表或数组中的一个元素,如果该元素不存在,则返回 null(不能用于 Set)。
val list = listOf(0, 1, 2)
println(list.getOrNull(2)) // 2
println(list.getOrNull(3)) // null,因为这个列表没有第四个元素,索引从 0 开始

你可以使用 list[3] 代替,但这样会引发异常,而 getOrNull() 则会在任何情况下返回一个值。

  • randomOrNull():像 getOrNull() 一样,如果集合为空,它返回 null,否则返回一个随机元素。
val list = listOf(0, 1, 2)
val list1 = listOf<Int>()println(list.randomOrNull()) // 返回一个元素
println(list1.randomOrNull()) // null,因为集合为空

firstOrNull()lastOrNull():允许我们设置特定的条件。如果集合中至少有一个元素满足条件,它们会返回该元素。
区别是:

  • firstOrNull() 会返回集合中 第一个满足条件的元素。如果没有满足条件的元素,它会返回 null

  • lastOrNull() 会返回集合中 最后一个满足条件的元素。如果没有满足条件的元素,它也会返回 null

val list = listOf(0, 1, 1, 2, 5, 7, 6)
val num = list.firstOrNull { it > 3 }
val num1 = list.lastOrNull { it == 1 }

最小值和最大值(可空)

Kotlin 为集合提供了许多方便的比较工具——包括处理可空元素的工具。以下是它们的简介:

  • minOrNull() / maxOrNull():返回集合中的最大或最小元素,如果集合为空,则返回 null

  • minByOrNull() / maxByOrNull():返回满足条件的最大或最小元素,如果没有符合条件的元素,则返回 null

  • minOfOrNull() / maxOfOrNull():返回元素特性(如值、大小等)上的最大或最小值,若集合为空则返回 null

  • minWithOrNull() / maxWithOrNull():返回满足条件的最大或最小元素,指定了 compareBy {} 块。

  • minOfWithOrNull() / maxOfWithOrNull():返回符合条件的元素特性上的最大或最小值,指定了 compareBy {} 块。

我们这里只提到这些函数,详细的示例和讲解可以参考“集合的聚合操作”一节。

有一点需要注意:这些函数都有没有 “OrNull” 后缀的对应版本。曾几何时,这些“没有 OrNull” 的函数是合法的工具。但从 Kotlin 1.4.0 开始,这些函数(如 min()max()minBy()maxBy()minWith()maxWith())被重命名为 minOrNull()maxOrNull() 等,且老版本的函数已标记为废弃。到了 Kotlin 1.7.0,这些废弃的函数重新引入,作为它们各自 “OrNull” 对应版本的非空替代品。这些非空版本返回一个集合元素,或者在集合为空时抛出异常。所以使用时要小心!

结论

我们已经讨论了如何处理具有可空元素的集合以及一些便捷的方法。以下是几个要点:

  • Kotlin 中有可空集合、具有可空元素的集合和空集合,它们是不同的。

  • listOfNotNull()setOfNotNull() 函数帮助我们从包含空值的序列中创建非空集合。

  • 我们可以检查集合是否为空,或者集合中是否有元素满足某些条件,确保不会抛出异常。

  • 我们可以使用比较函数如 minOrNull()maxOrNull() 等,选择并显示集合元素或其特性。

  • 这些函数有对应的非空版本,它们在集合为空时会抛出异常,而不是返回 null

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

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

相关文章

nextjs编程式跳转

Next.js 中&#xff0c;你可以通过多种方式实现编程式导航&#xff08;即通过代码而非 <Link> 组件跳转页面&#xff09;。以下是完整的实现方法&#xff1a; 1. 使用 useRouter Hook&#xff08;函数组件&#xff09; 这是最常用的方法&#xff0c;适用于函数组件&#…

Git Remote命令介绍:远程仓库管理

一、Git Remote 是什么 git remote主要用于管理远程仓库&#xff0c;可以轻松地与远程仓库进行交互&#xff0c;实现代码的共享与同步 。 二、Git Remote 的作用 &#xff08;一&#xff09;连接桥梁 假设你正在参与一个大型的 Web 应用开发项目&#xff0c;团队成员分布在…

Android开发中的11种行为型设计模式深度解析

在Android应用开发中&#xff0c;设计模式是解决特定问题的可重用方案&#xff0c;其中行为型设计模式尤其重要&#xff0c;它们专注于对象之间的通信和职责分配。本文将深入解析Android开发中最常用的11种行为型设计模式&#xff0c;每个模式都配有详细的介绍和实际应用示例&a…

Python 模块未找到?这样解决“ModuleNotFoundError”

在 Python 开发中&#xff0c;遇到“ModuleNotFoundError”时&#xff0c;通常是因为 Python 解释器无法找到你尝试导入的模块。这可能是由于多种原因导致的&#xff0c;比如模块未安装、路径不正确、虚拟环境未激活等。今天&#xff0c;就让我们一起探讨如何解决“ModuleNotFo…

Numpy库,矩阵形状与维度操作

目录 一.numpy库简介与安装 numpy库的安装 二.numpy核心功能 1.矩阵处理 2.数学运算 三.数据的维度与属性 1.维度管理 2.属性方法 四.数据类型与存储范围 五.矩阵形状与维度操作 六.数据升维与reshape()方法 一.numpy库简介与安装 NumPy是Python中用于科学计算的核心…

图论(2):最短路

最短路一、模板1. Floyd2. 01BFS3. SPFA4. Dijkstra&#xff08;弱化版&#xff09;5. Dijkstra&#xff08;优化版&#xff09;二、例题1. Floyd1.1 传送门1.2 无向图最小环1.3 灾后重建1.4 飞猪2. 01BFS2.1 Kathiresan2.2 障碍路线2.3 奇妙的棋盘3. SPFA3.1 奶牛派对3.2 营救…

“融合进化,智领未来”电科金仓引领数字化转型新纪元

一、融合进化 智领未来电科金仓2025产品发布会重磅开启&#xff01; 7月15日&#xff0c;以“融合进化 智领未来”为主题的电科金仓2025产品发布会在北京举办。产品发布会上展示了四款代表未来数字化趋势的创新性产品。这些产品不仅涵盖了数据库技术&#xff0c;还涉及到数据集…

常规笔记本和加固笔记本的区别

在现代科技产品中&#xff0c;笔记本电脑因其便携性和功能性被广泛应用。根据使用场景和需求的不同&#xff0c;笔记本可分为常规笔记本和加固笔记本&#xff0c;二者在多个方面存在显著区别。适用场景是区分二者的重要标志。常规笔记本主要面向普通消费者和办公人群&#xff0…

Shell 脚本编程全面学习指南

前言Shell 脚本编程是 Linux 和 Unix 系统管理、自动化任务的核心工具之一。通过 Shell 脚本&#xff0c;你可以自动化重复性操作、简化复杂流程、提高系统管理效率&#xff0c;甚至构建完整的自动化运维工具。本文将带你从基础到进阶&#xff0c;全面学习 Shell 脚本编程&…

DelayQueue延迟队列的使用

1、DelayQueue简介 DelayQueue 也是 Java 并发包&#xff08;java.util.concurrent&#xff09;中的一个特殊队列,用于在指定的延迟时间之后处理元素。 DelayQueue的一些关键特性&#xff1a; 延迟元素处理&#xff1a;只有当元素的延迟时间到期时&#xff0c;元素才能被取出…

QT6 源,七章对话框与多窗体(6) 颜色对话框 QColorDialog :本类的属性,信号函数,静态成员函数,以及源代码

&#xff08;1&#xff09;本类的继承关系如下 &#xff1a;&#xff08;2&#xff09; 对于本标准颜色对话框来讲&#xff0c;学会使用其静态函数以获取到颜色就足够了。&#xff08;3&#xff09; 开始学习本类的静态成员函数 &#xff1a;&#xff08;4&#xff09;测试一下…

金仓数据库:融合进化,智领未来——2025年数据库技术革命的深度解析

引言 在数字中国战略的推动下&#xff0c;数据库作为数字经济的基础设施&#xff0c;正经历着前所未有的技术重构。2025年7月15日&#xff0c;电科金仓以"融合进化&#xff0c;智领未来"为主题&#xff0c;发布了新一代数据库产品矩阵&#xff0c;标志着国产数据库在…

【人工智能99问】卷积神经网络(CNN)的结构和原理是什么?(10/99)

文章目录卷积神经网络&#xff08;CNN&#xff09;的结构及原理一、CNN的核心结构1. 输入层&#xff08;Input Layer&#xff09;2. 卷积层&#xff08;Convolutional Layer&#xff09;2. 卷积层的核心机制&#xff1a;局部感受野与权值共享3. 池化层&#xff08;Pooling Laye…

CCF编程能力等级认证GESP—C++7级—20250628

CCF编程能力等级认证GESP—C7级—20250628单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)线图调味平衡单选题&#xff08;每题 2 分&#xff0c;共 30 分&…

《Python 类设计模式:属性分类(类属性 VS 实例属性)与方法类型(实例 / 类 / 静态)详解》

Python 类和对象&#xff1a;从 "图纸" 到 "实物" 的编程思维面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP &#xff09;是一种通过组织对象来编程的方法。1.初识类和对象&#xff1a;用生活例子看透核心概念1.1类-class物与类…

Eureka服务端启动

目录 1、相关文章 2、创建eureka-server子工程 3、父工程build.gradle引入版本依赖管理 4、子工程build.gradle引入依赖 5、将main重命名为EurekaApplication并修改代码 6、添加application.yml文件 7、启动工程并访问 8、访问界面如下 9、 完整目录结构 1、相关文章 …

AWS Partner: Sales Accreditation (Business)

AWS Partner: Sales Accreditation &#xff08;Business&#xff09;云概念和AWS云计算什么是云计算&#xff1f;计算的演变趋势云计算部署模型AWS 客户采用的模式为什么客户选择AWSAWS竞争优势高可用的全球基础设施AWS服务服务广度和深度AWS产品和服务服务类别AWS解决方案库A…

深入理解设计模式之中介者模式:解耦对象交互的利器

为什么需要中介者&#xff1f;在软件开发中&#xff0c;我们经常会遇到对象之间需要相互通信的场景。当系统规模较小时&#xff0c;对象直接相互引用并通信可能不会带来太大问题。但随着系统复杂度增加&#xff0c;对象间的交互关系会变得错综复杂&#xff0c;形成一个复杂的网…

从 0 安装 Label Studio:搭建可后台运行的数据标注平台(systemd 实践

本文将介绍如何使用 pip 安装 Label Studio&#xff0c;并通过 systemd 实现开机自启与后台运行&#xff0c;适用搭建个人项目的数据标注平台。 一、Label Studio 简介 Label Studio 是一个开源、跨模态的数据标注工具&#xff0c;支持文本、图像、音频、视频、HTML等多种类型…

【数据结构】链表(linked list)

目录 一、链表的介绍 二、单链表 1. 单链表的初始化 2. 单链表的插入 &#xff08;1&#xff09;动态申请一个节点 &#xff08;2&#xff09;头插法 &#xff08;3&#xff09;尾插法 &#xff08;4&#xff09;按照位置来插入 &#xff08;5&#xff09;在地址之前插…