Kotlin 标准库提供了一整套用于管理集合的工具,集合是可变数量(可能为零)的一组条目,各种集合对于解决问题都具有重要意义,并且经常用到。
集合通常包含相同类型的一些(数目也可以为零)对象。集合中的对象称为元素或条目。例如,一个系的所有学生组成一个集合,可以用于计算他们的平均年龄。 以下是 Kotlin 相关的集合类型:
Kotlin 让你可以独立于所存储对象的确切类型来操作集合。换句话说,将 String
添加到 String
list 中的方式与添加 Int
或者用户自定义类的到相应 list 中的方式相同。 因此,Kotlin 标准库为创建、填充、管理任何类型的集合提供了泛型的(通用的,双关)接口、类与函数。
这些集合接口与相关函数位于 kotlin.collections 包中。
Kotlin 标准库提供了基本集合类型的实现: set、list 以及 map。 一对接口代表每种集合类型:
val numbers = mutableListOf("one", "two", "three", "four")
numbers.add("five") // 这是可以的
//numbers = mutableListOf("six", "seven") // 编译错误
更改可变集合不需要它是以 var 定义的变量:写操作修改同一个可变集合对象,因此引用不会改变。 但是,如果尝试对 val
集合重新赋值,你将收到编译错误。
对比Java,Kotlin只是增加了"不可变"集合框架的接口,没有另起炉灶,复用Java API的所有实现类型。
提供了丰富易用的方法,例如forEach/map/flatMap。Scala也是一门JVM语言,Kotlin很多特性都参考了Scala。
运算符级别的支持,简化集合框架的访问。
Java中的类型 | ||
---|---|---|
有自己的类型,所以是"一等公民",可以赋值、传递,并在合适的条件下调用。 以下是各种函数的用法,关键点都写在注释当中了:
创建集合的最常用方法是使用标准库函数:listOf
如果以逗号分隔的集合元素列表作为参数,编译器会自动检测元素类型。创建空集合时,须明确指定类型。
// 这两个编译完成后都变成了java里面的List
val intList1: List = listOf(1,2,3) //不可变
val intList2: MutableList = mutableListOf(1,2,3) //可变
val intList4 = listOf(1,2,3)
val intList5 = mutableListOf(1,2,3)
// 创建空集合的时候需要指定类型
val intList6 = mutableListOf()
// 对于 List,有一个接受 List 的大小与初始化函数的构造函数,该初始化函数根据索引定义元素的值。
val doubled1 = List(3, { it * 2 })
println(doubled1) // 输出结果: [0, 2, 4]
// 如果你想操作这个集合,应使用 MutableList
val doubled2 = MutableList(3, { it * 2 })
println(doubled2) // 输出结果: [0, 2, 4]
// "name" to "oLiver" 可以理解为K—V键值对
// Any等价于java中的Object
val map1: Map = mapOf("name" to "oLiver", "age" to 30)
val map2: MutableMap = mutableMapOf("name" to "oLiver", "age" to 30)
val map4 = mapOf("name" to "oLiver", "age" to 30)
val map5 = mutableMapOf("name" to "oLiver", "age" to 30)
// 创建空集合的时候需要指定类型
val map6 = mutableMapOf()
val set1: Set = setOf("one", "two", "three", "four")
val set2: MutableSet = mutableSetOf("one", "two", "three", "four")
val numbersSet1 = setOf("one", "two", "three", "four")
val numbersSet2 = mutableSetOf("one", "two", "three", "four")
// 创建空集合的时候需要指定类型
val emptySet = mutableSetOf()
// 快捷方式创建:ArrayList = java.util.ArrayList
// ArrayList 叫做类型别名,他是指向于java相对于的工具类
// 包括HashMap,HashSet,LinkedHashMap,LinkedHashSet等都是类型别名
val stringList = ArrayList()
要创建与现有集合具有相同元素的集合,可以使用复制操作。标准库中的集合复制操作创建了具有相同元素引用的 浅 复制集合。 因此,对集合元素所做的更改会反映在其所有副本中。
val sourceList = mutableListOf(1, 2, 3)
val referenceList = sourceList
referenceList.add(4)
println(sourceList.joinToString()) // 输出结果:1, 2, 3, 4
println(referenceList.joinToString()) // 输出结果:1, 2, 3, 4
集合的初始化可用于限制其可变性。例如,如果构建了一个 MutableList
的 List
引用,当你试图通过此引用修改集合的时候,编译器会抛出错误。
val sourceList = mutableListOf(1, 2, 3)
val referenceList: List = sourceList
//referenceList.add(4) // 编译错误
sourceList.add(4)
println(referenceList.joinToString()) // 显示 sourceList 当前状态, 输出结果:1, 2, 3, 4
println(sourceList.joinToString()) // 显示 sourceList 当前状态, 输出结果:1, 2, 3, 4
在特定时刻通过集合复制函数,例如toList()、toMutableList()、toSet() 等等。创建了集合的快照。 结果是创建了一个具有相同元素的新集合 如果在源集合中添加或删除元素,则不会影响副本。副本也可以独立于源集合进行更改。
val sourceList = mutableListOf(1, 2, 3)
val copyList = sourceList.toMutableList()
val readOnlyCopyList = sourceList.toList()
sourceList.add(4)
println("Copy: ${copyList.joinToString()}") // Copy: 1, 2, 3
println("sourceList: ${sourceList.joinToString()}") // sourceList: 1, 2, 3, 4
println("readOnlyCopyList: ${readOnlyCopyList.joinToString()}") // readOnlyCopyList: 1, 2, 3
//readOnlyCopyList.add(4) // 编译异常
println("Read-only copy size: ${readOnlyCopyList.size}")
这些函数还可用于将集合转换为其他类型,例如根据 List 构建 Set,反之亦然。
val sourceList = mutableListOf(1, 2, 3)
val copySet = sourceList.toMutableSet()
copySet.add(3)
copySet.add(4)
println(copySet.joinToString()) // 输出结果:1, 2, 3, 4
val intList3: MutableList = mutableListOf() //不可变
for (i in 0 .. 10) {
intList3.add(i) // 往后添加
}
println(intList3) // 输出结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
val stringList2 = ArrayList()
val stringList3 = ArrayList()
for (i in 0 .. 10) {
stringList2.add("num:$i")
stringList3 += "num:$i" // 运算符可以重载,这里 += 的用途相当于add
}
println(stringList2) // 输出结果:[num:0, num:1, num:2, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]
println(stringList3) // 输出结果:[num:0, num:1, num:2, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]
val stringList3 = ArrayList()
for (i in 0 .. 10) {
stringList3 += "num:$i" // 运算符可以重载,这里 += 的用途相当于add
}
println(stringList3) // 输出结果:[num:0, num:1, num:2, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]
stringList3.remove("num:2")
println(stringList3) // 输出结果是:[num:0, num:1, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]
stringList3 -= "num:6"
println(stringList3) // 输出结果:[num:0, num:1, num:3, num:4, num:5, num:7, num:8, num:9, num:10]
val stringList3 = ArrayList()
for (i in 0 .. 10) {
stringList3 += "num:$i" // 运算符可以重载,这里 += 的用途相当于add
}
println(stringList3) // 输出结果:[num:0, num:1, num:2, num:3, num:4, num:5, num:6, num:7, num:8, num:9, num:10]
stringList3[0] = "HelloWorld" // 也可以根据角标来修改对应角标的值
val valueAt5 = stringList3[0]
println(valueAt5) // 输出结果:HelloWorld
println(stringList3)
val map2: MutableMap = mutableMapOf("name" to "oLiver", "age" to 30)
val map3 = HashMap()
println(map2) // 输出结果:{name=oLiver, age=30}
println(map3) // 输出结果:{}
map2["age"] = 10
map3["age"] = 10
println(map2) // 输出结果:{name=oLiver, age=10}
println(map3) // 输出结果:{age=10}
println(map3["age"]) // 输出结果:10
对于遍历集合元素, Kotlin 标准库支持 迭代器 的常用机制——对象可按顺序提供对元素的访问权限,而不会暴露集合的底层结构。 当需要逐个处理集合的所有元素(例如打印值或对其进行类似更新)时,迭代器非常有用。
Iterable
val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
println(numbersIterator.next())
}
遍历 Iterable
集合的另一种方法是众所周知的 for
循环。在集合中使用 for
循环时,将隐式获取迭代器。因此,以下代码与上面的示例等效:
val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
println(item)
}
最后,有一个好用的 forEach()
函数,可自动迭代集合并为每个元素执行给定的代码。因此,等效的示例如下所示:
val numbers = listOf("one", "two", "three", "four")
numbers.forEach {
println(it)
}
对于列表,有一个特殊的迭代器实现: ListIterator 它支持列表双向迭代:正向与反向。 反向迭代由 hasPrevious() 和 previous() 函数实现。 此外, ListIterator 通过 nextIndex() 与 previousIndex() 函数提供有关元素索引的信息。
具有双向迭代的能力意味着 ListIterator
在到达最后一个元素后仍可以使用。
val numbers = listOf("one", "two", "three", "four")
val listIterator = numbers.listIterator()
while (listIterator.hasNext()) listIterator.next()
println("Iterating backwards:")
while (listIterator.hasPrevious()) {
print("Index: ${listIterator.previousIndex()}")
println(", value: ${listIterator.previous()}")
}
/**
* Iterating backwards:
Index: 3, value: four
Index: 2, value: three
Index: 1, value: two
Index: 0, value: one
* */
为了迭代可变集合,于是有了 MutableIterator 来扩展 Iterator 使其具有元素删除函数 remove() 。因此,可以在迭代时从集合中删除元素。
val numbers = mutableListOf("one", "two", "three", "four")
val mutableIterator = numbers.iterator()
mutableIterator.next()
mutableIterator.remove()
println("After removal: $numbers") // After removal: [two, three, four]
除了删除元素, MutableListIterator 还可以在迭代列表时插入和替换元素。
val numbers = mutableListOf("one", "four", "four")
val mutableListIterator = numbers.listIterator()
mutableListIterator.next()
mutableListIterator.add("two")
mutableListIterator.next()
mutableListIterator.set("three")
println(numbers) // [one, two, three, four]
Pair,就是对,键值对的意思,包含两个元素,Triple则包含三个元素
// 创建键值对的两种方式
val pair1 = "key" to "value"
val pair2 = Pair("key", "value")
println(pair1) // 输出结果:(key, value)
println(pair2) // 输出结果:(key, value)
//获取对应的元素,第一个和第二个
val first = pair1.first
val second = pair1.second
println(first) // 输出结果:key
println(second) // 输出结果:value
// 解构,创建一个x,y的解构,来存储键值对
val (x, y) = pair2
println(x) // 输出结果:key
println(y) // 输出结果:value
// Triple 包含三个元素, 使用方法和Pair一样
val triple = Triple("key", 2, 3.0)
val first = triple.first
val second = triple.second
val third = triple.third
val (x, y, z) = triple
println(first) // 输出结果:key
println(second) // 输出结果:2
println(third) // 输出结果:3.0
println(x) // 输出结果:key
println(y) // 输出结果:2
println(z) // 输出结果:3.0