news 2026/4/24 23:38:47

kotlin基础(6):在 Kotlin 中使用集合

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kotlin基础(6):在 Kotlin 中使用集合

在 Kotlin 中使用集合

无需多言

学习内容:

  • 如何创建和修改数组。
  • 如何使用ListMutableList
  • 如何使用SetMutableSet
  • 如何使用MapMutableMap

这几个如果有开发经验的同学应该知道其中的区别,但是为了预防万一还是贴一个表格

特性数组 (Array)列表 (List)集 (Set)
顺序有固定顺序,按索引访问有固定顺序,按索引访问通常无顺序LinkedHashSet可保留插入顺序)
重复元素允许重复允许重复不允许重复(基于equals()/hashCode()
长度固定,创建后不可变可变(MutableList)或不可变(List可变(MutableSet)或不可变(Set
元素类型在 JVM 上可存储基本类型(IntArray等)避免装箱只能存储对象类型(Int会装箱)只能存储对象类型
常用操作性能随机访问 O(1) 增删(末尾模拟)需创建新数组 O(n)ArrayList:随机访问 O(1),末尾增删摊销 O(1),中间增删 O(n)LinkedList:随机访问 O(n),头部增删 O(1)HashSet:增删查平均 O(1)LinkedHashSet:O(1) + 维护顺序TreeSet:O(log n) 且有序
Kotlin 创建方式arrayOf(1,2,3)intArrayOf(1,2,3)listOf(1,2,3)不可变mutableListOf(1,2,3)setOf(1,2,3)不可变mutableSetOf(1,2,3)

数组

我们不说 那些索引啊什么的那些东西了,比较基础查一下就行

Array代表多个值。具体而言,数组是属于同一数据类型的一系列值。(不能像Python一样,别搞混了)

  • 数组包含多个值,这些值称为元素,有时也称为项。
  • 数组中的元素是有序的,可以通过索引进行访问。

关于索引还是提一嘴:

  • 通过索引可以快速地访问数组元素。您可以通过索引访问数组的任何随机元素,并且访问任何其他随机元素预计需要大约相同的时间。因此,有人说数组具有随机访问特性。
  • 数组具有固定的大小。这意味着您向数组添加元素时不能超过该数组的大小。如果尝试访问某个数组(包含 100 个元素)中位于索引 100 处的元素,则会引发异常,因为最高索引为 99(请注意,第一个索引为 0,而不是 1)。但是,您可以修改数组中位于相关索引处的值。

如需在代码中声明数组,请使用arrayOf()函数。

arrayOf()函数将数组元素作为形参,并返回类型与传入的形参相符的数组。

这可能与您看到的其他函数略有不同,因为arrayOf()的参数数量会变化。

如果您向arrayOf()传入两个参数,生成的数组将包含两个元素(索引为 0 和 1)。如果您传入三个实参,生成的数组将包含 3 个元素,索引为 0 到 2。

我们来举个例子:

valrockPlanets=arrayOf<String>("Mercury","Venus","Earth","Mars")

由于 Kotlin 使用类型推断,因此在调用arrayOf()时可以省略类型名称。在rockPlanets变量下方,添加另一个变量gasPlanets,而不将类型传递到尖括号中。

valgasPlanets=arrayOf("Jupiter","Saturn","Uranus","Neptune")

可以使用数组进行一些很酷的操作。例如,就像数字类型IntDouble一样,您可以同时添加两个数组。创建一个名为solarSystem的新变量,并使用加号 (+) 运算符将其设为rockPlanetsgasPlanets的结果。结果是一个新数组,其中包含rockPlanets数组的所有元素以及gasPlanets数组的元素。

valsolarSystem=rockPlanets+gasPlanets

访问数组元素

无需多言

您还可以按索引设置数组元素的值。

注意一点:

您无法调整数组的大小

如果实验超出索引的值则会报错ArrayIndexOutOfBounds异常

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 8 out of bounds for length 8

如果你需要增加数组的现有大小,需要创建一个新数组:

valnewSolarSystem=arrayOf("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto")

或者

valarray1=arrayOf(1,2,3)valnewArray=array1+5// 直接加上,结果 [1, 2, 3, 5]

这时候就能用了

列表

列表是有序且可调整大小的集合,通常作为可调整大小的数组实现。当数组达到容量上限时,如果您尝试插入新元素,需要将该数组复制到一个新的较大数组。

使用列表,您还可以在特定索引处(介于其他元素之间)插入新元素。

在大多数情况下,无论列表中包含多少个元素,向列表中添加任何元素所需的时间都是相同的。

ListMutableList

ListMutableList有什么用?

  • List是一个接口,用于定义与只读有序项集合相关的属性和方法。
  • MutableList通过定义修改列表的方法(例如添加和移除元素)来扩展List接口。

这些接口仅指定List和/或MutableList的属性和方法。每个属性和方法的实现方式均由扩展这些接口的类决定。上述基于数组的实现将是您最常使用(如果不是始终使用)的实现,但 Kotlin 允许其他类扩展ListMutableList

listOf()函数

arrayOf()类似,listOf()函数将相关项作为形参,但返回List,而不是数组。

  1. main()中移除现有代码。
  2. main()中,通过调用listOf()创建名为solarSystem的行星List
funmain(){valsolarSystem=listOf("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune")}
  1. List具有size属性,用于获取列表中的元素数量。输出solarSystem列表的size
println(solarSystem.size)
  1. 运行代码。列表的大小应为 8。
8

访问列表中的元素

与数组一样,您可以使用下标语法从List访问特定索引处的元素。

如下:

println(solarSystem[2])println(solarSystem.get(2))//或者这样

除了按索引获取元素之外,您还可以使用indexOf()方法搜索特定元素的索引。

indexOf()方法在列表中搜索指定元素(作为实参传入),并返回该元素在第一次出现时的索引。如果该元素未出现在列表中,则返回-1

上实例:

输出对solarSystem列表调用indexOf()并传入"Earth"的结果。

println(solarSystem.indexOf("Earth"))//存在,且位于2处println(solarSystem.indexOf("Pluto"))//不存在

那么其输出应为:

2 -1

使用for循环遍历列表元素

在学习函数类型和 lambda 表达式时,您已经了解如何使用repeat()函数多次执行代码。

编程中的一项常见任务是对列表中的每个元素执行一次某个任务。Kotlin 包含一个名叫for循环的功能,可利用简洁易懂的语法来实现此目的。这通常称为“循环遍历”列表或“遍历”列表。

是不是很熟悉?那就对了。

in关键字之前的变量未使用valvar进行声明,它假定为 get-only。您可以随意为其命名。

如果列表使用的是复数名称(如planets),则通常将该变量命名为单数形式,例如planet。将该变量命名为itemelement的情况也很常见。

我们来举个实例吧:您需要使用for循环在单独的一行上输出每个行星名称。

您可以写如下代码:

for(planetinsolarSystem){println(planet)}

会得到输出:

Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune

向列表中添加元素

只有实现MutableList接口的类具有在集合中添加、移除和更新元素的功能。如果你需要创建要向其中添加元素和从中移除元素的列表时,您需要专门调用mutableListOf()函数,而不是listOf()

add()函数有两个版本:

  • 第一个add()函数具有一个属于列表中元素类型的参数,并将其添加到列表末尾。
  • add()的另一个版本有两个参数。第一个参数对应于应该插入新元素的索引。第二个参数是要添加到列表中的元素。

不多说,直接上案例:

valsolarSystem=mutableListOf("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune")//先创建一个MutableListsolarSystem.add("Pluto")//第一种用法,添加末尾solarSystem.add(3,"Theia")//第二种用法,添加到指定位置

更新特定索引处的元素

你也可以用下标更改现有元素:

solarSystem[3]="Future Moon"println(solarSystem[3])println(solarSystem[9])

会得到:

Future Moon Pluto

从列表中移除元素

使用remove()removeAt()方法可移除元素。您可以通过两种方法移除元素:将该元素传递到remove()方法中,或者使用removeAt()按索引移除该元素。

上实例:

solarSystem.removeAt(9)solarSystem.remove("Future Moon")

验证元素是否存在

List可提供contains()方法,该方法可在列表中存在某个元素时返回Boolean。输出为"Pluto"调用contains()的结果。

println(solarSystem.contains("Pluto"))

更简洁的语法是使用in运算符。您可以使用元素、in运算符和集合来检查该元素是否在列表中。使用in运算符检查solarSystem是否包含"Future Moon"

println("Future Moon"insolarSystem)

输出应该为:

false false

集是指没有特定顺序且不允许出现重复值的集合

如此集合的实现(初学可以略过,但是很有意思)

秘诀是哈希代码。哈希代码是由任何 Kotlin 类的hashCode()方法生成的Int。可以将其视为 Kotlin 对象的半唯一标识符。如果对该对象稍作更改,例如向String中添加一个字符,则会产生截然不同的哈希值。虽然两个对象可以使用相同的哈希代码(称为哈希冲突),但hashCode()函数可在某种程度上确保唯一性,大多数情况下,两个不同的值各自具有唯一的哈希代码。

集使用哈希代码作为数组索引。当然,可能会有大约 40 亿个不同的哈希代码,因此Set不仅仅是一个巨型数组。您可以将Set视为一个列表数组。最外层的数组(左侧以蓝色勾勒出的数字)分别对应一个可能的哈希代码范围(也称为“分区”)。每个内部列表(右侧以绿色阴影表示)均表示集中的各个项。由于哈希冲突相对罕见,即使潜在索引有限,每个数组索引处的内部列表也分别只有一两个项,除非添加了数万个或数十万个元素。

集具有两个重要属性:

  1. 与列表相比,可以更快地搜索集中的特定元素,尤其是对于大型集合。虽然ListindexOf()要求从头开始检查每个元素,直到找到匹配项,但平均而言,检查某个元素是否在集中所用的时间相同,无论它是第一个元素还是第十万个元素。
  2. 对于相同数量的数据,集占用的内存往往比列表多,因为所需的数组索引通常比集中的数据多。

与普遍的观点相反,检查集中是否含有某个元素所用的时间是不固定的,实际上取决于集中的数据量。不过,由于哈希冲突通常很少见,因此需要检查的元素数量仍然比搜索列表中的项要小几个数量级。

集的优势在于确保唯一性。如果您要编写一个程序来跟踪新发现的行星,则可以借助集轻松检查是否已发现某颗行星。如果数据量很大,通常最好检查列表中是否存在某个元素,这需要遍历所有元素。

ListMutableList一样,既有Set也有MutableSetMutableSet会实现Set,因此任何实现MutableSet的类都需要同时实现这两者。

在 Kotlin 中使用MutableSet

valsolarSystem=mutableSetOf("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune")println(solarSystem.size)//输出其大小solarSystem.add("Pluto")//其也有add方法,但是不确定位置println(solarSystem.size)//再输出一下看看println(solarSystem.contains("Pluto"))//是否已经存在

输出应该为:

8 9 true

注意:您也可以使用in运算符检查某个元素是否在集合中,例如:"Pluto" in solarSystem相当于solarSystem.contains("Pluto")

如前所述,集不能包含重复项。请尝试重新添加"Pluto"

solarSystem.add("Pluto")println(solarSystem.size)

大小不会增加:

9

remove()函数接受一个参数,并从集中移除指定的元素。

solarSystem.remove("Pluto")println(solarSystem.size)println(solarSystem.contains("Pluto"))

则输出应该为:

8 false

不要问为什么其没有removeAt,因为它是无序的

映射集合

(Map)

Map是由键和值组成的集合。之所以称之为映射,是因为唯一键会映射到其他值。键及其附带的值通常称为key-value pair

映射的键具有唯一性,但映射的值不具有唯一性。两个不同的键可以映射到同一个值。例如,"Mercury"0颗卫星,"Venus"也有0颗卫星。

通过相应的键访问映射的值通常比在大型列表中(例如使用indexOf())搜索值更快。

您可以使用mapOf()mutableMapOf()函数声明映射。映射需要两个泛型类型(以英文逗号隔开),一个用于键,另一个用于值。

如果映射具有初始值,则还可以使用类型推断。要使用初始值填充映射,每个键值对都由以下部分组成:首先是键,后跟to运算符,而后是值。每个键值对均以英文逗号隔开。

我们来演示一下:

valsolarSystem=mutableMapOf("Mercury"to0,"Venus"to0,"Earth"to1,"Mars"to2,"Jupiter"to79,"Saturn"to82,"Uranus"to27,"Neptune"to14)

其也有size输出:

println(solarSystem.size)

也可以通过下标设置(新)键值对:

solarSystem["Pluto"]=5

也可以这样获取:

println(solarSystem["Pluto"])println(solarSystem.get("Theia"))

remove()方法可移除具有指定键的键值对。它也会返回已移除的值,或者如果指定的键不在映射中,则返回null

solarSystem.remove("Pluto")println(solarSystem.size)//验证一下

下标语法或put()方法也可以修改已存在的键的值。使用下标语法将 Jupiter 的卫星数量更新为 78,并输出新值。

solarSystem["Jupiter"]=78println(solarSystem["Jupiter"])

摘要

  • 数组存储的是同一类型的有序数据,且具有固定大小。
  • 数组用于实现很多其他集合类型。
  • 列表是可调整大小的有序集合。
  • 集是无序集合,不能包含重复项。
  • 映射的工作方式与集类似,用于存储指定类型的键/值对。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 23:38:18

明日方舟MAA助手:全自动游戏管家解放你的双手

明日方舟MAA助手&#xff1a;全自动游戏管家解放你的双手 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手&#xff0c;全日常一键长草&#xff01;| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitcode.com…

作者头像 李华
网站建设 2026/4/24 23:37:39

一线观察:杨浦全铝定制生产商的真实表现

在全铝定制领域&#xff0c;木制全屋定制虽有传统审美优势&#xff0c;但随着消费升级&#xff0c;其痛点日益突出。数据表明&#xff0c;木材受温湿度影响大&#xff0c;在南方梅雨季、北方干燥采暖季&#xff0c;易出现膨胀、收缩、开裂、变形等问题&#xff1b;人造板生产中…

作者头像 李华
网站建设 2026/4/24 23:34:04

带依赖的多关键点求最短路问题

一.迪杰斯特拉算法模板&#xff1a; using Pair pair<int, int>; const int N 1e5 10; const int INF 1e18; // 使用 long long 的最大值 int n, m, s, dis[N]; vector<Pair> G[N]; // 邻接表void dijkstra(int x) {priority_queue<Pair, vector<Pair&g…

作者头像 李华
网站建设 2026/4/24 23:30:48

uniapp适配H5和Android-apk实现获取当前位置经纬度并调用接口

index.vue:注意&#xff1a;这里的 return https://www.******.com/bus_admin_java 这里是区分 H5和apk调用接口地址的不同而设置的。之后凡是调用接口的方法就使用封装后的request&#xff08;&#xff09;<template><view class"container"><view c…

作者头像 李华