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

Kotlin集合与空值

我们已经学习了 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():允许我们设置特定的条件。如果集合中至少有一个元素满足条件,它们会返回该元素。
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.dtcms.com/a/284291.html

相关文章:

  • 产品经理如何绘制流程图
  • Linux中的数据库操作基础
  • SpringMVC 执行原理
  • 79、【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:r7 寄存器
  • Modbus
  • PyCharm2024安装包社区版和专业版
  • TESOLLO五指灵巧手遥操作解决方案
  • 使用 .NET Core 的原始 WebSocket
  • Spring整合MyBatis详解
  • 概率论与数理统计(四)
  • WCDB soci 查询语句
  • 缓存雪崩、缓存穿透,缓存击穿
  • 使用IntelliJ IDEA和Maven搭建SpringBoot集成Fastjson项目
  • 【git】使用教程
  • CommonJS和ES模块区别对比
  • API开发提速新方案:SmartBear API Hub与ReadyAPI虚拟化整合实践
  • ESP8266服务器建立TCP连接失败AT+CIPSTART=“TCP“,“192.168.124.1“,8080 ERROR CLOSED
  • JAVA后端开发——success(data) vs toAjax(rows): 何时用
  • 美拍sig逆向
  • 神经网络:模拟人脑的 AI 信息处理系统
  • 代码随想录打卡第十二天
  • Unity | AmplifyShaderEditor插件基础(第十集:噪声的种类+火焰制作-下)
  • 透过结构看时间——若思考清洗则表达有力
  • 开源Agent平台Dify源码剖析系列(六)核心模块core/agent之CotCompletionAgentRunner
  • Web开发 01
  • Vue.js 的 Composition API 深度解析:构建高效可维护的前端逻辑
  • 让大模型输出更加规范化——指定插件
  • LVS部署DR模式集群
  • @Linux搭建DNS-主从服务器
  • Spring原理揭秘--Spring的AOP