1.集合概述
kotlin
集合主要有三类
- List 是一个有序集合,可通过索引(反映元素位置的整数)访问元素。
- Set 集合中的元素是唯一的,不可重复。
- Map(或者字典)是一组键值对。
1.1 集合类型
集合结构可以用以下两种归纳来区分:
-
一个 只读 接口,提供访问集合元素的操作。
-
一个 可变 (可读可写)接口,通过写操作扩展相应的只读接口:添加、删除和更新其元素。
而集合的只读并不是通过val来修饰,也就是说并不能使得该集合只读。他只是保障了该集合的引用是不可变的,如下所示:
val numbers = mutableListOf("one", "two", "three", "four")
fun main() {
numbers.add("five")//
println(numbers)
numbers = mutableListOf("one", "two", "three", "four")//error: val cannot be reassigned
}
kotlin
集合接口如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mNRnCyyb-1596274969133)(http://www.kotlincn.net/assets/images/reference/collections-overview/collections-diagram.png)]
1.2 Collection
可以看到Collection实现了Iterable
接口,它定义了迭代操作的实现。同时Collection定义了集合的公共行为,比如说检索大小等。
fun printAll(strings: Collection<String>) {
for(s in strings) print("$s ")
println()
}
fun main() {
val stringList = listOf("one", "two", "one")
printAll(stringList)
val stringSet = setOf("one", "two", "three")
printAll(stringSet)
}
MutableCollections
在Collection的基础上增加了add以及
remove等修改操作。
1.3 List
List顺序存储元素,并且可以通过索引取值。这点容易理解,比较值得注意的是两个List之间的对比。如果两个列表对应的值一样,那么我们就可以认定其相等的:
data class Person(var name:String,var age:Int)
fun main() {
val bob = Person("Bob", 31)
val people = listOf<Person>(Person("Adam", 20), bob, bob)
val people2 = listOf<Person>(Person("Adam", 20), Person("Bob", 31), bob)
println(people == people2)
bob.age = 32
println(people == people2)
}
1.4 Set
首先set是无顺序的,null也可以时Set的元素。当两个Set的元素可以一一对应且相等的时候,那么就可以判断两个set是相等的.
Set还有两个实现LinkHashSet
以及HashSet
.LinkHashSet
是Set的默认实现,保留了顺序的特性也提供了依赖于顺序的函数.而HashSet
不依赖于顺序,当时其所需的内存更少
1.5 Map
Map的用法和java
差不多.重点是如何判断两个Map是相等的:
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)
val anotherMap = mapOf("key2" to 2, "key1" to 1, "key4" to 1, "key3" to 3)
println("The maps are equal: ${
numbersMap == anotherMap}")//无论键值对的顺序如何,包含相同键值对的两个 Map 是相等的
和Set差不多,加个Mutable就转变为了可修改的集合.默认的实现是LinkHashMap
,他是有顺序的.而另一个实现是HashMap
,他是不带顺序的.
2. 构造集合
2.1 集合的初始化
首先说说只读集合的情况,List和Set可以用List()以及Set().Map的话有mapOf
(),而键值对可以通过以下的方式赋值:
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)
这种写法直观明了,但是它会创建一个临时的Pair对象,因此还是比较耗性能的。可以用其他方式来赋值:
val numbersMap = mutableMapOf<String, String>().apply {
this["one"] = "1"; this["two"] = "2" }
只读集合的空集合,他可以用三个方式表示:emptyList()
、emptySet()
与 emptyMap()
。其中创建空集合时,应指定集合所包含的的元素类型。
接下来说说可变集合的表示方法,他么比不可变集合多了个mutable,其他差不多:mutableMapOf()
,mutableListOf<T>()
、mutableSetOf<T>()
。
2.2 List的初始化函数
List可以用函数来初始化。List后面跟着一个小括号,左边是该List 的大小,右边是构造函数。
val doubled = List(3, {
it * 2 }) // 不可边集合,it代表的是索引号
val mutableDoubled = MutableList(3, {
it * 2 }) // 可变集合
println(doubled)
2.3 各个具体类型的创建
具体类型的集合可以用过List这种基本类型装饰而成:
val linkedList = LinkedList<String>(listOf("one", "two", "three"))
2.4 集合的复制
首先是浅拷贝,也就是创建特定存在集合的新引用:
val sourceList = mutableListOf(1, 2, 3)
val referenceList = sourceList
referenceList.add(4)//referenceList改变的同时,sourceList也发生了变化
同时初始化的时候也可以改变其可变性:
val sourceList = mutableListOf(1, 2, 3)
val referenceList: List<Int> = sourceList
接下来是深拷贝,通过集合复制函数来创建独立的副本,例如toList()
、toMutableList()
、toSet()
:
val sourceList = mutableListOf(1, 2, 3)
val copyList = sourceList.toMutableList()
val readOnlyCopyList = sourceList.toList()
这些函数还可用于将集合转换为其他类型,例如根据 List 构建 Set,反之亦然。
val sourceList = mutableListOf(1, 2, 3)
val copySet = sourceList.toMutableSet()
2.5 调用其他集合的函数
可以通过其他集合的各种操作来生成新的集合,比如说过滤。
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter {
it.length > 3 }
新的集合也可以通过其他集合的映射得出:
val numbers = setOf(1, 2, 3)
println(numbers.map {
it * 3 })
println(numbers.mapIndexed {
idx, value -> value * idx })
Map可以通过集合的关联来生成:
val numbers = listOf("one", "two", "three", "four")
println(numbers.associateWith {
it.length })//{one=3, two=3, three=5, four=4}
3. 迭代器
3.1 基本用法
主要有三种遍历方式:1.Iterable
集合的方式,该方式遍历到集合尾部的时候就不能再用了。2.for
循环的方式.3.foreach
的方式。
val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
println(numbersIterator.next())
}
val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
println(item)
}
val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
println(item)
}
3.2 双向迭代器
双向迭代的能力意味着可以向后迭代也可以向前迭代,即便是迭代道最后一个元素也可以继续使用:
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()}")
}