# Kotlin教程 - 7 容器
什么是容器?
容器就是可以存储多个数据的一种数据类型,容器内的每一个数据称之为元素,其中的元素可以是任意类型的数据,包括字符串、数字、布尔,甚至是容器等等。
例如有一个班级,有40个学生,我们肯定不能定义40个变量来存储学生的信息,有1000个人,那不要命了,我们可以将所有学生的信息放到容器中。
在 Kotlin 中常用的容器分为4类:
- 数组(Array)
- 列表(List)
- 集合(Set)
- 字典(Map)
不同的容器有不同的特点,例如:
- 是否支持重复的元素,有的容器中的元素不能重复,有的可以。
- 是否有序
下面一一介绍。
# 7.1 数组
数组是一种有序的容器,用于存储相同类型的元素。
数组的主要特点:
- 有序
- 只能存储相同类型的元素
- 大小在创建的时候就确定了,大小不可变
# 1 创建数组
方式1:arrayOf
fun main() {
// 创建一个用于存储整数的数组,并存储了1、2、3、4、5
val numberArray1: Array<Int> = arrayOf(1, 2, 3, 4, 5)
// 类型也可以省略
val numberArray2 = arrayOf(1, 2, 3, 4, 5)
}
2
3
4
5
6
方式2:创建空组数
fun main() {
// 创建一个空数组,长度为5,后面可以修改数组中的值
val emptyArray = arrayOfNulls<String>(5)
}
2
3
4
方式3:数组构造函数
fun main() {
// 创建一个整形数组,长度为5,其中的元素都是0
val numberArray = Array(5) { 0 }
// 创建一个字符串类型数组,长度为5,其中的元素都是空字符串
val stringArray = Array(5) { "" }
// 创建一个可空的字符串数组,长度为5,其中的元素都是null
val nullableArray = Array<String?>(5) { null }
// 创建一个整数数组,长度为5,并将元素初始化为索引的两倍,则其中的元素为[0, 2, 4, 6, 8]
val numberArray2 = Array(5) { index -> index * 2 }
// 创建一个字符串数组,长度为5,其中的元素使用when表达式通过index进行设置,最后的结果["Hello","old","are","you","!"]
val stringArray2 = Array(5) { index ->
when (index) {
0 -> "Hello"
1 -> "old"
2 -> "are"
3 -> "you"
4 -> "!"
else -> throw IndexOutOfBoundsException("数组索引越界") // 异常后面再讲
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
使用数组构造函数创建,还可以使用 lambda 表达式,根据 index
来设置元素。
方式4:使用原生整数数组类型
以下以 IntArray
为例, IntArray
是一个整形数组,与泛型数组 Array<Int>
不同,IntArray
是一个特定于整数的数组类型。
举个栗子:
fun main() {
// 使用IntArray构造函数初始化,长度为5,初始值为 0 的数组
val numbers1 = IntArray(5)
// 使用 intArrayOf 函数 创建一个包含指定元素的数组
val numbers2 = intArrayOf(1, 2, 3, 4, 5)
}
2
3
4
5
6
7
Kotlin 中除了 IntArray
,还有一些其他的原生数组类型,以及泛型数组类型。以下是一些常见的数组类型:
IntArray
:用于存储整数。DoubleArray
:用于存储双精度浮点数。FloatArray
:用于存储单精度浮点数。LongArray
:用于存储长整数。ShortArray
:用于存储短整数。ByteArray
:用于存储字节。CharArray
:用于存储字符。BooleanArray
:用于存储布尔值。
这些原生数组类型直接使用底层的原生数据类型,因此具有高效的性能。
# 2 基础操作
# 获取长度
使用 size()
方法可以获取到数组的长度。
fun main() {
val numbers: Array<Int> = arrayOf(1, 2, 3, 4, 5)
println("数组长度:" + numbers.size) // 输出:5
}
2
3
4
# 访问元素
可以使用下标来访问列表中的元素或修改数组中的元素,从0开始,注意不要越界,下标越界会报错。
fun main() {
val numbers: Array<Int> = arrayOf(1, 2, 3, 4, 5)
var num = numbers[0] // 获取第一个元素
println(num) // 输出:1
num = numbers[numbers.lastIndex] // 获取最后一个元素
println(num) // 输出:5
numbers[0] = 100 // 修改元素
println(numbers[0])
}
2
3
4
5
6
7
8
9
10
11
因为数组的长度创建后就无法更改了,所以我们无法删除和添加更多到元素到数组中,只能修改数组中的元素。
除了使用 [index] 的方式访问元素,还可以使用 get 函数来访问。
举个栗子:
fun main() {
val numbers: Array<Int> = arrayOf(1, 2, 3, 4, 5)
val num1 = numbers.get(0) // 获取第一个元素
val num6 = numbers.getOrElse(6) { 0 } // 获取index为6的元素
val num7 = numbers.getOrNull(7) ?: 0 // 获取index为7的元素
}
2
3
4
5
6
- 可以使用
get(index)
函数获取指定index
的元素,如果index
大于数组长度,或报错; - 可以使用
getOrElse(Index)
获取指定index
的元素,如果越界,则返回lambda
表达式的结果; - 可以使用
getOrNull(Index)
获取指定index
的元素,如果越界,则返回null
,在上面的代码中,我们结合?:
操作符,如果为null
,就赋 0 。
Kotlin 还提供了一些获取指定位置元素的函数。
举个栗子:
fun main() {
val numbers: Array<Int> = arrayOf(1, 2, 3, 4, 5)
val firstElement = numbers.first() // 获取第一个额原始
val lastElement = numbers.last() // 获取最后一个元素
}
2
3
4
5
# 3 遍历数组
使用 for-in
循环
可以使用 for-in
循环来遍历数组的元素。这适用于所有类型的数组,包括原生数组和泛型数组。
fun main() {
val colors = arrayOf("Red", "Blue", "Green")
for (color in colors) { // 依次取出数组中的每个元素
println(color)
}
}
2
3
4
5
6
7
使用索引和 indices
属性
如果需要访问数组的索引以及元素,可以使用数组的 indices
属性,然后通过索引来访问元素。
fun main() {
val colors = arrayOf("Red", "Blue", "Green")
for (index in colors.indices) { // index 每个元素的索引
println("Index: $index, Element: ${colors[index]}") // 通过索引取出每个元素
}
}
2
3
4
5
6
7
使用 forEach
函数
Kotlin 提供了 forEach
函数,可用于遍历数组元素。这对于处理集合更加方便。
fun main() {
val colors = arrayOf("Red", "Blue", "Green")
colors.forEach { element ->
println(element) // 依次取出数组中的元素
}
}
2
3
4
5
6
7
使用 forEachIndexed
函数
如果需要同时访问索引和元素,可以使用 forEachIndexed
函数。
fun main() {
val colors = arrayOf("Red", "Blue", "Green")
colors.forEachIndexed { index, element ->
println("Index: $index, Element: $element")
}
}
2
3
4
5
6
7
使用迭代器
还可以通过获取数组的迭代器来遍历元素。
fun main() {
val colors = arrayOf("Red", "Blue", "Green")
val iterator = colors.iterator() // 获取数组的迭代器对象,通过迭代器对象取出数组中的元素
while (iterator.hasNext()) { // 判断是否有下一个元素
val color = iterator.next() // 取出下一个元素
println(color)
}
}
2
3
4
5
6
7
8
# 7.2 List
List 也是一个有序的容器,和数字很像,但是它的长度是可以变化的,所以我们可以随时添加和删除其中的元素,List主要有如下特点:
- 列表中的元素可以重复
- 列表中的元素可以修改,可以增加、修改、删除
- 列表中的元素是有序的,可以通过索引来访问
- 列表中可以存储不同数据类型的数据
# 1 创建List
创建可变的List
// 创建一个空的可变List
val list1 = mutableListOf<String>()
// 创建了一个包含三个元素的List
var list2 = mutableListOf("Doubi", "Shabi" ,"Niubi")
2
3
4
5
创建不可变List
// 创建一个包含三个整数的不可变List
val immutableList = listOf(1, 2, 3)
// 创建一个不可变的空List
val emptyList = emptyList<String>()
2
3
4
5
不可变列表不允许添加、删除或修改其中的元素。
但是一个不能添加元素的空列表有什么用呢?
有时候可能希望在某个函数中返回一个空集合作为默认值,而不是 null。这样可以避免空指针异常,并使代码更加健壮。
# 2 基础操作
# 可变和不可变转换
不可变 List 和可变 List 可以相互转换。
fun main() {
val list1 = listOf<String>()
val list2 = list1.toMutableList() // 将不可变list转换为可变list
list2.add("Doubi")
}
2
3
4
5
可以使用 List 的 toMutableList() 方法将不可变 List 转换为可变的 List。注意,原 List 不变,得到的是一个新的可变的 List。
同样,可以将可变 List 转换为 不可变 List。
fun main() {
val list1 = mutableListOf<String>()
val list2 = list1.toList() // 将可变list转换为不可变list
}
2
3
4
# 添加元素
fun main() {
// 创建一个空的可变List
val list = mutableListOf<String>()
list.add("Doubi") // 添加元素
list += "Niubi" // 添加元素
println(list) // [Doubi, Niubi]
}
2
3
4
5
6
7
除了可以使用 add()
方法添加元素,还可以使用 +=
运算符添加元素。这在C++中叫运算符重载。
也可以使用 addAll
方法将其他容器中的元素全部添加到 List 中:
val list = mutableListOf<String>()
list.addAll(mutableListOf("Caibi", "Mengbi"))
2
# 获取长度
可以使用 size
属性来获取 List 的长度:
// 创建一个空的可变List
val list = mutableListOf<String>("Doubi", "Shabi", "Niubi")
println(list.size) // 通过size属性获取长度
2
3
# 访问元素
可以使用下标来访问列表中的元素,从0开始,如果可能越界,可以使用 getOrElse
或 getOrNull
获取。
fun main() {
// 创建一个空的可变List
val list = mutableListOf<String>("Doubi", "Shabi", "Niubi")
val firstElement1 = list[0] // 通过下标来访问第一个元素
val firstElement2 = list.first() // 访问第一个元素
var lastElement1 = list.last() // 获取最后一个元素
var lastElement2 = list[list.lastIndex] // 通过下标获取最后一个元素
var element1 = list.get(1)
var element5 = list.getOrElse(5) { "Doubi" } // 如果越界,则返回lambda的值
var element6 = list.getOrNull(6) ?: "Doubi" // 如果越界,返回null值,可以结合?:操作符来进行空处理
}
2
3
4
5
6
7
8
9
10
11
12
13
14
和数字的操作方式基本是一样的。
# 插入元素
可以使用 add(index, element)
方法在指定位置插入元素:
val list = mutableListOf("Doubi", "Shabi", "Niubi")
list.add(1, "Caibi") // 在索引 1 处插入元素
println(list) // 输出:[Doubi, Caibi, Shabi, Niubi]
2
3
也可以使用 addAll
方法插入其他的列表或集合:
val list = mutableListOf("Doubi", "Shabi", "Niubi")
list.addAll(mutableListOf("Caibi", "Jianbi")) // 在List末尾添加另一个list中的所有元素
list.addAll(1, mutableListOf("Caibi", "Jianbi")) // 在索引 1 处插入另一个list中的所有元素
2
3
4
# 删除元素
fun main() {
val list = mutableListOf("Red", "Green", "Blue", "Yellow", "Pink", "Blue", "Blue")
list.removeFirst() // 删除第一个元素
list.removeLast() // 删除最后一个元素
list.removeAt(1) // 按照索引删除元素
list.remove("Blue") // 删除列表中所有的Blue元素
list -= "Yellow" // 删除Yellow元素
println(list)
}
2
3
4
5
6
7
8
9
除了可以使用 remove
相关的方法删除,还可以使用 -=
运算符进行删除。
我们还可以使用 lambda 表达式进行判断,然后删除指定的元素。
举个栗子:
fun main() {
val list = mutableListOf("Red", "Green", "Blue", "Yellow", "Pink", "Blue", "Blue")
list.removeIf { it == "Blue" } // 根据条件删除,删除所有的 Blue
println(list)
}
2
3
4
5
在上面使用 removeIf
函数,结合 lambda 表达式,根据指定的条件删除元素。it
表示 List 中的每一个元素。
# 清空List
val list = mutableListOf("Doubi", "Shabi", "Niubi")
list.clear()
2
# 3 遍历List
遍历 List 和遍历 数组的方式是一样的。
使用 for-in
循环
可以使用 for-in
循环来遍历数组的元素。
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
for (element in list) { // 依次取出数组中的每个元素
println(element)
}
}
2
3
4
5
6
7
使用索引和 indices
属性
如果需要访问数组的索引以及元素,可以使用数组的 indices
属性,然后通过索引来访问元素。
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
for (index in list.indices) { // index 每个元素的索引
println("Index: $index, Element: ${list[index]}") // 通过索引取出每个元素
}
}
2
3
4
5
6
7
使用 forEach
函数
Kotlin 提供了 forEach
函数,可以结合 lambda 表达式进行遍历
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
list.forEach {
println(it)
}
}
2
3
4
5
6
使用 forEachIndexed
函数
如果需要同时访问索引和元素,可以使用 forEachIndexed
函数。
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
list.forEachIndexed { index, element ->
println("Index: $index, Element: $element")
}
}
2
3
4
5
6
7
使用迭代器
还可以通过获取数组的迭代器来遍历元素。
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
val iterator = list.iterator() // 获取数组的迭代器对象,通过迭代器对象取出数组中的元素
while (iterator.hasNext()) { // 判断是否有下一个元素
val color = iterator.next() // 取出下一个元素
println(color)
}
}
2
3
4
5
6
7
8
9
# 4 解构
什么是解构?
解构就是用集合 List 一次性给多个变量赋值。
举个栗子:
fun main() {
val list = mutableListOf("Red", "Green", "Blue")
val (one, two, three) = list
println(three) // Blue
}
2
3
4
5
在上面的代码中,通过 List 同时给 one 、two、three 三个变量赋值。
注意,被赋值的变量要比 List 的元素少,如果比 List 的元素多会报错。
如果想取其中的某几个元素,该如何操作呢,例如 List 有5个元素,想取其中的第1个和第4个元素给变量赋值。
fun main() {
val list = mutableListOf("Red", "Green", "Blue", "Yellow" , "Gray")
val (str1, _, _, str2) = list
println(str1) // Red
println(str2) // Yellow
}
2
3
4
5
6
在上面的代码中,分别用第1个和第4个元素给变量 str1 和 变量 str2 赋值,忽略的元素使用 _
占位。
# 5 其他常用操作
# 判断 List 是否为空
在 Kotlin 中,可以使用 isEmpty()
方法判断 List 是否为空,使用 isNotEmpty()
方法判断 List 是否不为空。
val numbers = mutableListOf<Int>()
if (numbers.isEmpty()) {
println("集合为空")
}
numbers.addAll(listOf(1, 2, 3, 4, 5))
if (numbers.isNotEmpty()) {
println("集合不为空")
}
2
3
4
5
6
7
8
9
# 检查是否包含某个元素
在 Kotlin 中,你可以使用 contains()
方法来检查是否包含某个元素。
val numbers = listOf(1, 2, 3)
println(numbers.contains(2)) // true
2
# 将 List 中的元素拼接成字符串
在 Kotlin 中,可以使用 joinToString()
函数将 List 中的元素使用指定的连接符拼接成一个字符串。
val numbers = listOf(1, 2, 3)
val numberString = numbers.joinToString(", ")
println(numberString) // 输出:1, 2, 3
2
3
# 将字符串分割成 List
在 Kotlin 中,可以使用 split()
函数将一个字符串使用指定的分隔符分割成一个 List。
val str = "1,2,3,4,5"
val list = str.split(",")
println(list) // 输出:[1, 2, 3, 4, 5]
2
3
# 使用 List 中的元素生成新的 List
在 Kotlin 中,你可以使用 map()
函数来处理 List 中的元素,然后生成一个新的 List。
val numbers = listOf(1, 2, 3)
val doubledNumbers = numbers.map { it * 2 }
println(doubledNumbers) // [2, 4, 6]
2
3
# 过滤 List 中的元素
在 Kotlin 中,可以使用 filter()
函数来过滤 List 中的元素,生成一个新的 List。
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // [2, 4]
2
3
在上面,通过 filter()
函数,过滤满足 it % 2 == 0
的元素,形成一个新的 List。
# 判断 List 中的元素是否有元素满足指定条件
在 Kotlin 中,可以使用 any()
函数来判断 List 中是否有元素满足指定的条件。
val numbers = listOf(1, 2, 3, 4, 5)
val f = numbers.any { it % 2 == 0 }
println(f) // true
2
3
# 判断 List 中的元素是否都满足指定条件
在 Kotlin 中,可以使用 all()
函数来判断 List 中所有的元素是否都满足指定的条件。
val numbers = listOf(1, 2, 3, 4, 5)
val f = numbers.all { it % 2 == 0 }
println(f) // false
2
3
# 7.3 Set
在 Kotlin 中,Set 与 List 有一些不同之处:Set 是一种容器类型,不允许包含重复元素,而且 Set 是无序的。Set 主要用于集合运算,例如求交集、并集、差集等。
Set 的主要特点包括:
- 不允许重复元素
- 无序,不能保证元素的顺序
- 可以被修改
- 可以存储不同的数据类型
# 1 创建 Set
创建可变的 Set 的方式,可以向其中添加或删除元素。
// 创建一个空的 Set
val emptySet = mutableSetOf<String>()
// 创建一个包含元素的 Set
val colorSet = mutableSetOf("Red", "Green", "Blue")
// 使用其他 List 或 Set 来创建
val fruits = setOf("apple", "banana", "orange").toMutableSet()
2
3
4
5
6
7
8
创建不可变的 Set 的方式,其中的元素不可修改。
// 创建一个空的 Set
val emptySet = setOf<String>()
// 创建一个包含元素的 Set
val fruits = setOf("apple", "banana", "orange")
2
3
4
5
# 2 基础操作
# 可变与不可变转换
不可变 Set 和可变 Set 可以相互转换。
将不可变 Set 转换为可变 Set:
fun main() {
val colorSet = setOf("red", "green", "blue")
val newColorSet = colorSet.toMutableSet()
val newColorList = colorSet.toMutableList()
}
2
3
4
5
可以使用 Set 的 toMutableSet() 方法将不可变 Set 转换为可变的 Set。注意,原 Set 不变,得到的是一个新的可变的 Set。
甚至还可以使用 toMutableList()
方法直接转换为可变的 List。
同样,可以将可变 Set 转换为 不可变 Set 或 不可变 List。
fun main() {
// 创建一个包含元素的 Set
val colorSet = mutableSetOf("Red", "Green", "Blue")
val newColorSet = colorSet.toSet() // 得到一个新的不可变的Set
val newColorList = colorSet.toList() // 得到一个新的不可变的List
}
2
3
4
5
6
所以 List 和 Set 可以相互转换,还可以相互在可变和不可变之间进行转换。
所以如果我们想去掉 List 中的重复元素可以进行如下操作:
fun main() {
val list1 = listOf<String>("red", "red", "green", "blue")
val list2 = list1.toSet().toList() // 先变Set再转回List
println(list2) // [red, green, blue]
}
2
3
4
5
可以先将有重复元素的 List 转换为 Set,然后再转换为 List。 但其实 List 有提供去重的方法,如下:
fun main() {
val list1 = listOf<String>("red", "red", "green", "blue")
val list2 = list1.distinct() // 去重
println(list2) // [red, green, blue]
}
2
3
4
5
可以使用 distinct() 方法去掉重复的元素。
# 添加元素
可以使用 add()
、+=
、addAll()
向 Set 中添加元素:
fun main() {
val numbers = mutableSetOf<Int>()
numbers.add(1) // 可以使用add方法添加元素
numbers += 2 // 可以使用运算符来添加元素
numbers.addAll(listOf(3, 4, 5)) // 可以使用addAll添加其他容器
}
2
3
4
5
6
# 访问元素
在 Java或其他很多语言中因为 Set 是无序的,所以无法通过下标来访问 Set 中的元素。如果要访问 Set 中的元素,只能通过迭代方式来获取。
但是 Kotlin 比较牛逼,可以使用下标来访问,真是小刀拉屁股——开眼了。
举个栗子:
fun main() {
// 创建一个包含元素的 Set
val colors = setOf("red", "green", "blue")
val element1 = colors.elementAt(0)
val element5 = colors.elementAtOrElse(5) { "black" } // 获取index为8的元素,获取不到就使用lambda返回black
val element6 = colors.elementAtOrNull(6) ?: "black" // 获取index为9的元素,获取不到就返回null,结合?:操作符返回black
}
2
3
4
5
6
7
和 List 提供的方法是一样的。
那么问题来了,它是如何实现的,什么原理呢?
其实底层是使用迭代器来遍历 Set,依次取出 Set 中的元素,然后使用取出的次数当索引来返回指定的元素。
突如起来的骚气,差点闪到我的老妖。所以这个索引意义不大,和添加的顺序很可能不一致。
当然我们可以创建 LinkedHashSet
,这个是有序的 Set,那么索引就意义了。
举个栗子:
fun main() {
// 创建可变LinkedHashSet
val linkedHashSet1 = LinkedHashSet<String>()
linkedHashSet1.add("red")
linkedHashSet1.add("red")
linkedHashSet1.add("green")
println(linkedHashSet1) // [red, green]
// 创建不可变LinkedHashSet
val linkedHashSet2 = linkedSetOf("red", "red", "green")
println(linkedHashSet2) // [red, green]
}
2
3
4
5
6
7
8
9
10
11
12
如果想创建有序的 Set,可以使用上面的方式来创建可变或不可变的有序 Set。
# 获取长度
你可以使用 size
属性来获取 Set 的长度:
val numbers = setOf(1, 2, 3)
println(numbers.size) // 3
2
# 删除元素
举个栗子:
fun main() {
// 创建一个包含元素的 Set
val colorSet = mutableSetOf("red", "green", "blue", "yellow", "gray", "black")
colorSet.remove("red")
colorSet -= "green" // 使用 -= 删除
colorSet.removeIf() { it == "blue" } // 删除元素是blue的元素
colorSet.removeAll(listOf("yellow", "gray")) // 使用容器批量删除
println(colorSet) // [black]
}
2
3
4
5
6
7
8
9
可以使用 remove
、-=
来删除,也可以使用 removeIf
通过 lambda 表达式来过滤进行删除。
还可以根据容器批量删除 Set 中的元素。
# 清空 Set
你可以使用 clear()
方法来清空 Set:
val numbers = mutableSetOf(1, 2, 3)
numbers.clear()
println(numbers) // []
2
3
# 将 Set 转换为 List
使用 toList()
方法可以将 Set 转换为 List:
val numbers = setOf(1, 2, 3)
val numList = numbers.toList()
println(numList) // [1, 2, 3]
2
3
# 3 遍历 Set
在 Kotlin 中,遍历 Set 可以使用多种方式,包括 for
循环、forEach()
方法、for-in
循环以及迭代器。以下是这些方法的示例:
使用 for-in
循环
val fruits = setOf("apple", "banana", "orange")
for (fruit in fruits) {
println(fruit)
}
2
3
4
5
使用 forEach()
方法
val fruits = setOf("apple", "banana", "orange")
fruits.forEach { fruit ->
println(fruit)
}
2
3
4
5
使用迭代器
val fruits = setOf("apple", "banana", "orange")
val iterator = fruits.iterator()
while (iterator.hasNext()) {
val fruit = iterator.next()
println(fruit)
}
2
3
4
5
6
7
使用 for
循环
因为 Set 没有索引,所以可以使用 Set.toList()
方法将 Set 转换为 List,并使用 List.size
属性确定 List 的长度,然后使用 for
循环遍历 List 中的元素。
val fruits = setOf("apple", "banana", "orange")
val fruitsList = fruits.toList()
for (i in 0 until fruitsList.size) {
println(fruitsList[i])
}
2
3
4
5
6
# 4 其他常用操作
# 判断 Set 是否为空
可以使用 isEmpty()
方法判断 Set 是否为空,使用 isNotEmpty()
方法判断 Set 是否不为空:
val numbers = setOf<Int>()
if (numbers.isEmpty()) {
println("Set为空")
}
val numbers2 = setOf(1, 2, 3, 4, 5)
if (numbers2.isNotEmpty()) {
println("Set不为空")
}
2
3
4
5
6
7
8
9
# 检查是否包含某个元素
你可以使用 contains()
方法来检查 Set 是否包含某个元素:
val numbers = setOf(1, 2, 3)
println(numbers.contains(2)) // true
2
# 将 Set 中的元素拼接为字符串
可以使用 joinToString()
函数将 Set 中的元素使用指定的连接符拼接为一个字符串:
val numbers = setOf(1, 2, 3)
val numberString = numbers.joinToString(", ")
println(numberString) // "1, 2, 3"
2
3
# 使用 Set 中的元素生成新的 Set
与 List 一样,在 Kotlin 中,你可以使用 map()
方法处理 Set 中的元素,然后生成一个新的 Set:
val numbers = setOf(1, 2, 3)
val squaredNumbers = numbers.map { it * 2 }.toSet()
println(squaredNumbers) // [2, 4, 6]
2
3
Set 也提供了 filter()
、any()
、every()
方法,可以用来过滤、检查是否有元素满足条件以及是否所有元素都满足条件。
# 并集、交集和差集
在 Kotlin 中,Set 提供了 union()
、intersect()
和 subtract()
方法,可以用来执行并集、交集和差集操作。
并集示例:
val set1 = setOf(1, 2, 3)
val set2 = setOf(3, 4, 5)
val unionSet = set1.union(set2)
println(unionSet) // [1, 2, 3, 4, 5]
2
3
4
交集示例:
val set1 = setOf(1, 2, 3)
val set2 = setOf(3, 4, 5)
val intersectionSet = set1.intersect(set2)
println(intersectionSet) // [3]
2
3
4
差集示例:
val set1 = setOf(1, 2, 3)
val set2 = setOf(3, 4, 5)
val differenceSet = set1.subtract(set2)
println(differenceSet) // [1, 2]
2
3
4
这些操作在 Kotlin 的 Set 中非常有用,可以方便地执行集合运算。
# 7.4 Map
Map是一种键值对的数据结构,其中每个键对应一个值。
例如有一份数据:
姓名 | 成绩 |
---|---|
zhangsan | 94 |
lisi | 96 |
wangwu | 91 |
在Kotlin中,可以使用Map
来存储这种键值对数据,将姓名作为键,成绩作为值:
val studentGrades = mapOf(
"zhangsan" to 94,
"lisi" to 96,
"wangwu" to 91
)
2
3
4
5
通过 to 关键字来设置 key 和 value。
这样可以很容易通过姓名键获取对应的成绩值。
# 1 创建Map
创建可变Map
// 创建一个包含元素的可变Map
val studentGrades = mutableMapOf(
"zhangsan" to 94,
"lisi" to 96,
"wangwu" to 91
)
// 创建一个空可变Map
val emptyMap = mutableMapOf<String, Int>()
2
3
4
5
6
7
8
9
这种方式创建的Map
是可变的(mutable),你可以随时添加、修改或删除键值对。
没有指定类型的时候,Kotlin会自动推断键和值的数据类型。
创建不可变Map
// 创建一个包含元素的不可变Map
val studentGrades = mapOf(
"zhangsan" to 94,
"lisi" to 96,
"wangwu" to 91
)
// 创建一个空不可变Map
val emptyMap = emptyMap<String, Int>()
2
3
4
5
6
7
8
9
这种方式创建的Map
是不可变的(immutable),意味着一旦初始化后,不能再修改其中的键值对。
其实 to
是一个函数,创建的是一个 Pair() 对象。
所以我们也可以直接创建 Pair
对象,举个栗子:
val studentGrades = mapOf(
Pair("zhangsan", 94),
Pair("lisi", 96),
Pair("wangwu", 91)
)
2
3
4
5
当然了,我们一般不会这么写。
# 2 基础操作
# 添加元素
fun main() {
val numbers = mutableMapOf<String, Int>()
numbers["one"] = 1 // 添加或修改,会覆盖或修改之前的值
numbers.put("one", 2) // 添加或修改,会覆盖或修改之前的值
numbers += "two" to 2 // 添加或修改,会覆盖或修改之前的值
val value2 = numbers.putIfAbsent("two", 3) // 如果key存在就不添加,并返回存在的value,如果key不存在就添加,返回null
println(value2) // 2
val value3 = numbers.getOrPut("three") { 4 } // 获取指定的key元素,若不存在则将该元素加入到map中,并返回value,如果存在就不添加,并返回value
println(value3)
println(numbers) // {one=2, two=2, three=4}
}
2
3
4
5
6
7
8
9
10
11
12
putIfAbsent 和 getOrPut 的区别:
- putIfAbsent:如果key存在就不添加,并返回存在的value,如果key不存在就添加,返回null;
- getOrPut: 获取指定的key元素,如果存在就不添加,并返回value,如果key不存在就添加,也返回value。
# 访问元素
访问元素时,通过键来访问:
fun main() {
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
println(numbers["one"]) // 如果key不存在,返回null
println(numbers.get("two")) // 如果key不存在,返回null
println(numbers.getValue("two")) // 如果key不存在,报错
println(numbers.getOrDefault("two", "unknow")) // 如果key不存在,返回defalutValue
println(numbers.getOrElse("two") { "unknow" }) // 如果key不存在,返回lambda表达式结果
}
2
3
4
5
6
7
8
9
10
11
12
13
# 获取长度
获取Map的长度使用size
属性:
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
println(numbers.size) // 3
2
3
4
5
6
# 删除元素
删除元素通过键来进行操作:
val numbers = mutableMapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
numbers.remove("one") // 删除
numbers -= "two" // 删除
println(numbers) // {three=3}
2
3
4
5
6
7
8
9
# 清空Map
清空Map使用clear()
方法:
val numbers = mutableMapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
numbers.clear()
println(numbers) // {}
2
3
4
5
6
7
# 3 遍历操作
在Kotlin中,遍历Map可以使用for-in
循环、forEach
函数、keys
和values
属性:
使用for-in
循环
val studentGrades = mapOf(
"Alice" to 90,
"Bob" to 80,
"Charlie" to 85
)
for ((key, value) in studentGrades) {
println("$key - $value")
}
2
3
4
5
6
7
8
9
使用forEach
函数
val studentGrades = mapOf(
"Alice" to 90,
"Bob" to 80,
"Charlie" to 85
)
// 方式一,使用it
studentGrades.forEach {
println("${it.key} - ${it.value}")
}
// 方式二,使用key、value
studentGrades.forEach { (key, value) ->
println("$key - $value")
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
使用keys
和values
属性
val studentGrades = mapOf(
"Alice" to 90,
"Bob" to 80,
"Charlie" to 85
)
for (key in studentGrades.keys) {
val value = studentGrades[key]
println("$key - $value")
}
for (value in studentGrades.values) {
println("$value")
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4 其他常用操作
# 判断Map是否为空
可以通过isEmpty()
方法判断Map是否为空,通过isNotEmpty()
方法判断Map是否不为空:
val numbers = emptyMap<String, Int>()
if (numbers.isEmpty()) {
println("Map为空")
}
val studentGrades = mapOf(
"Alice" to 90,
"Bob" to 80,
"Charlie" to 85
)
if (studentGrades.isNotEmpty()) {
println("Map不为空")
}
2
3
4
5
6
7
8
9
10
11
12
13
# 检查包含某个键
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
println(numbers.containsKey("two")) // true
2
3
4
5
6
# 检查包含某个值
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
println(numbers.containsValue(2)) // true
2
3
4
5
6
# 获取Map中的所有键
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
val keys = numbers.keys.toList()
println(keys) // [one, two, three]
2
3
4
5
6
7
# 将Map中的键值对拼接为字符串
val numbers = mapOf(
"one" to 1,
"two" to 2,
"three" to 3
)
val numberString = numbers.entries.joinToString { (key, value) -> "$key: $value" }
println(numberString) // "one: 1, two: 2, three: 3"
2
3
4
5
6
7