- 基本概念
- 更改可变集合不需要它是以 var 定义的变量:写操作修改同一个可变集合对象,因此引用不会改变。 但是,如果尝试对 val 集合重新赋值,你将收到编译错误。
- 只读集合类型是型变的。 这意味着,如果类 Rectangle 继承自 Shape,则可以在需要 List
的任何地方使用 List
构造集合
创建集合最常用的方法是
[listOf<T>()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/list-of.html)、[setOf<T>()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/set-of.html)、[mutableListOf<T>()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-list-of.html)、[mutableSetOf<T>()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-set-of.html)val numberSet = setOf(1,2,3)val emptySet = mutableSetOf<String>()
同样的,Map的创建也有mapOf()和mutableMapOf()这两个函数,映射的键值对作为pair对象传递
//通常使用中缀函数to创建 val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 4) //to符号仅能创建一个短时存活的的pair对象,需要考虑性能问题时可创建Mutable的Map加apply函数 val numbersMap = mutableMapOf<String, String>().apply {this["one"] = "1";this["two"] = "2" }空集合,可用emptyList(),emptySet(),emptyMap()来创建空集合,同时应指定集合包含的元素类型
val empty = emptyList<String>()复制, 标准库中的集合是浅拷贝,深拷贝可用toList(),toMutableList(),toSet()等,在新的集合对元素进行操作不会影响副本 ```kotlin val sourceList = mutableListOf(1, 2, 3) val copyList = sourceList.toMutableList() val readOnlyCopyList = sourceList.toList() sourceList.add(4) println(“Copy size: ${copyList.size}”)
//readOnlyCopyList.add(4) // 编译异常 println(“Read-only copy size: ${readOnlyCopyList.size}”)
//这些函数还可以用于集合类型的转换
val sourceList = mutableListOf(1, 2, 3)
val copySet = sourceList.toMutableSet()
- 集合的初始化可用于限制其可变性。例如,如果构建了一个 MutableList 的 List 引用,当你试图通过此引用修改集合的时候,编译器会抛出错误
```kotlin
val sourceList = mutableListOf(1, 2, 3)
val referenceList: List<Int> = sourceList
//referenceList.add(4) // 编译错误
sourceList.add(4)
println(referenceList) // 显示 sourceList 当前状态
- 也可以通过其他操作来创建集合如过滤列表,映射和关联
//过滤列表 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 })
迭代器
- 迭代对每个元素操作主要有以下几个方法,然后List可以实现双向迭代通过previous( )来实现回溯。然后对于Mutable的集合可以进行remove,add和set等操作
//通过iterator()函数调用迭代器然后在调用next()函数返回元素 val numbers = listOf("one","two","three") val numbersIterator = numbers.iterator() while (numbersIterator.hasNext()) { println(numbersIterator.next()) } //for循环 for(item in numbers) { println(item) } //forEach()循环 numbers.forEach { println(it) }
- 迭代对每个元素操作主要有以下几个方法,然后List可以实现双向迭代通过previous( )来实现回溯。然后对于Mutable的集合可以进行remove,add和set等操作
序列
- 序列在处理多步骤集合时和Iterable不太相同,Sequence 对每个元素逐个执行所有处理步骤。 反过来,Iterable 完成整个集合的每个步骤,然后进行下一步,可避免生成中间步骤的结果,从而提高了整个集合处理链的性能,但同时序列的延迟性也会增加开销
创建序列用sequenceOf()函数
val numberSequence = sequenceOf("four","three","two","one")如果已经有了Iterable对象可以用asSequence()创建一个序列val numbers = listOf("one", "two", "three", "four") val numbersSequence = numbers.asSequence()可以用函数来构建序列
val oddNumbers = generateSequence(1) { it + 2 } // `it` 是上一个元素 println(oddNumbers.take(5).toList()) //此序列是无限的,最后一个元素是null时会停止创建也可以通过组块来生成序列,yield() 使用单个元素作为参数;yieldAll() 中可以采用 Iterable 对象、Iterable 或其他 Sequence
val oddNumbers = sequence { yield(1) yieldAll(listOf(3, 5)) yieldAll(generateSequence(7) { it + 2 }) }序列的操作,主要有无状态操作用来独立处理每个元素例如map()或filter(),也可以处理少量元素如take()和drop();有状态序列操作需要大量状态,通常与序列中元素数量成比例,下面的示例展示了序列和Iterable的区别 ```kotlin val words = “The quick brown fox jumps over the lazy dog”.split(“ “) val lengthsList = words.filter { println(“filter: $it”); it.length > 3 } .map { println(“length: ${it.length}”); it.length } .take(4)
println(“Lengths of first 4 words longer than 3 chars:”) println(lengthsList)

```kotlin
val words = "The quick brown fox jumps over the lazy dog".split(" ")
// 将列表转换为序列
val wordsSequence = words.asSequence()
val lengthsSequence = wordsSequence.filter { println("filter: $it"); it.length > 3 }
.map { println("length: ${it.length}"); it.length }
.take(4)
println("Lengths of first 4 words longer than 3 chars")
// 末端操作:以列表形式获取结果。
println(lengthsSequence.toList())

集合的转换
映射,基本的映射函数是map(),他将给定的lambda函数应用于每个后续元素,如果需要元素索引作为参数转换,使用函数mapIndexed(),可使用mapNotNull()
val numbers = setOf(1,2,3) println(numbers.map {it*3}) println(numbers.mapIndexed {idx, value -> value * idx}) //对于map可以选择映射键或者值 val numbersMap = mapOf("key1" to 1, "key2" to 2) println(numbersMap.mapKeys{ it.key.toUpperCase() }) println(numbersMap.mapValues{ it.value + it.key.length })合拢,zip()包两个list和成Pair 对象的列表,unzipping是从键值对中构建两个列表
val colors = listOf("red", "brown", "grey") val animals = listOf("fox", "bear", "wolf") println(colors zip animals) val twoAnimals = listOf("fox", "bear") println(colors.zip(twoAnimals)) [(red, fox), (brown, bear), (grey, wolf)] [(red, fox), (brown, bear)]关联,associateWith()创建一个Map,原始集合的元素是键;函数associateBy()根据元素的值返回键,如果元素的键相等就返回最后一个元素;最后还有associate()函数会生成临时的Pair()对象,可能会对性能有影响,下面是具体的示例 ```kotlin val numbers = listOf(“one”, “two”, “three”, “four”) println(numbers.associateWith {it.length} ) //{one=3, two=3, three=5, four=4} println(numbers.associateBy { it.first().uppercaseChar() } ) println(numbers.associateNy { keySelector = {it.first().upppercaseChar() }, valueTransform = {it.length} } ) {O=one, T=three, F=four} {O=3, T=5, F=4}
- 铺平flatten()可以在一个集合上调用,该函数返回嵌套集合中的多有元素的一个List
```kotlin
val numberSets = listOf(setOf(1,2,3), setOf(4,5,6))
println(numberSets.flatten())
集合的过滤
主要有filter(),fiterIndexed(),filterNot(),
val numbers = listOf("one", "two", "three", "four") val longerThan3 = numbers.fiter { it.length > 3 } val filteredIndex = numbers.fiterIndexed { index, s -> (index != 0)&&(s.length < 5) } val filteredNot = numbers.filterNot { it.length <=3 } //filterIsInstance() val numbers = listOf(null, 1, "two", 3.0, "four") numbers.filterIsInstance<String>().forEach { println(it.toUpperCase()) }partion(), 返回两个list一个是匹配的match另一个是不匹配的其余元素rest
val (match, rest) = numbers.partion {it.length > 3}
分组
val = listOf("one", "two", "three", "four", "five") println(numbers.groupBy {it.first.uppercaseChar()}) println(numbres.groupBy(keySelector = { it.first() }, valueTransform = {it.uppercaseChar() }))取部分集合
- slice(),返回具有给定集合元素的列表;take(),drop(),takeLast(),dropLast()
val numners = listOf("one", "two", "three", "four", "five", "six") println(numbers.silce(1..4 step 2)) println(numbers.silce(setOf(3,5,0))) println(numbers.take(3)) println(numbers.takeLast(3)) println(numbers.drop(1)) println(numbers.dropLast(5))
- slice(),返回具有给定集合元素的列表;take(),drop(),takeLast(),dropLast()
取单个元素
- elementAt(),第一个和最后一个元素:first() 和 last(),当指定位置超出集合范围时,elementAtOrNull()
val numbers = linkedSetOf("one", "two", "three", "four", "five") println(numbers.elementAt(3)) println(numbers.first()) println(numbers.last()) println(numbers.elementAtOrNull(5)) //按条件取 println(numbers.first{ it.length > 3 }) println(numbers.firstOrNull { it.length > 6 }) println(numbers.find { it % 2 == 0 })
- elementAt(),第一个和最后一个元素:first() 和 last(),当指定位置超出集合范围时,elementAtOrNull()
排序
- 基本的函数 sorted() 和 sortedDescending() 返回集合的元素,这些元素按照其自然顺序升序和降序排序, ```kotlin val numbers = listOf(“one”, “two”, “three”, “four”)
println(“Sorted ascending: ${numbers.sorted()}”) println(“Sorted descending: ${numbers.sortedDescending()}”)
- 自定义顺序,可以自定义排序的规则,也可以对用户自定义类型进行排序,让这个类型继承Comparable同时实现compareTo()函数即可。
```kotlin
val numbers = listOf("one", "two", "three", "four")
val sortedNumbers = numbers.sortedBy { it.length }
println("Sorted by length ascending: $sortedNumbers")
//通过Comparable实现版本号对比
class Version(val major: Int, val minor: Int): Comparable<Version> {
override fun compareTo(other: Version): Int {
if(this.major == other.major)
return this.minor - other.minor
else
return this.major - other.major
}
}
fun main() {
println(Version(1, 2) > Version(1, 3))
println(Version(2, 0) > Version(1, 5))
}
//可以用sortedWith()加Comparator来实现同样的效果
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
聚合操作
大多数的函数和其他语言中的没有区别,如下所示
val numbers = listOf(6,42,10,4) println("Count:${numbers.count()}") println("Max: ${numbers.maxOrNull()}") println("Min: ${numbers.minOrNull()}") println("Average: ${numbers.average()}") println("Sum: ${numbers.sum()}")也可以自定义Comparator对象来返回最大或最小元素
val numbers = listOf(5, 42, 10, 4) val min3Remainder = numbers.minBy { it % 3 } println(min3Remainder)函数 reduce() 和 fold(),它们依次将所提供的操作应用于集合元素并返回累积的结果。 操作有两个参数:先前的累积值和集合元素,fold() 接受一个初始值并将其用作第一步的累积值,而 reduce() 的第一步则将第一个和第二个元素作为第一步的操作参数
val numbers = listOf(5, 2, 10, 4) val sum = numbers.reduce { sum, element -> sum + element } val sumDoubled = numbers.fold(0) { sum, element -> sum + element * 2 }
集合的写操作
添加单个元素用add()函数,要将参数对象的每个元素添加到列表或集合中需要用addAll()函数
val numbers = mutableListOf(1, 2, 3, 4) numbers.add(5) //addAll() val numbers = mutableListOf(1, 2, 5, 6) numbers.addAll(arrayOf(7,8)) numbers.addAll(2,setOf(3,4))//第一个参数index可以指定插入开始的位置同时也可以使用plus运算符,如下所示
val numbers = mutableListOf("one", "two") numbers += "three" println(numbers) numbers += listOf("four", "five") println(numbers)删除元素使用remove()函数, 同时用removeAll()移除所有符合条件的元素,clear()清空所有元素,相对应的从集合中移除元素也可以用minus操作符,具体如下
val numbers = mutableListOf(1, 2, 3, 4, 3) numbers.remove(3) // 删除了第一个 `3` println(numbers) numbers.remove(5) // 什么都没删除 println(numbers) //removeAll() val numbers = mutableListOf(1, 2, 3, 4) println(numbers) numbers.removeAll { it >= 3 } println(numbers) numbers.clear() println(numbers) //minus val numbers = mutableListOf("one", "two", "three", "three", "four") numbers -= "three" numbers -= listOf("four", "five")
List及Set的相关操作
list按索引取单个元素
val numbers = listOf(1, 2, 3, 4) println(numbers.elementAt(index)) println(numbers.first()) println(numbers.last()) println(numbers.get(0)) println(numbers[0]) println(numbers.getOrNull(5)) // null println(numbers.getOrElse(5, {it})) // 5取列表的一部分用subList()
val numbers = (0..13).toList() println(numbers.subList(3,6))查找元素的位置
val numbers = listOf(1, 2, 3, 4, 2, 5) println(numbers.indexOf(2)) println(numbers.lastIndexOf(2)) val numbers = mutableListOf(1, 2, 3, 4) println(numbers.indexOfFirst { it > 2}) println(numbers.indexOfLast { it % 2 == 1})list的写操作 ```kotlin //添加 val numbers = mutableListOf(“one”,”five”,”six”) numbers.add(1,”two”) numbers.addAll(2, listOf(“three”, “four”)) println(numbers) //更新 val numbers = mutableListOf(“one”, “five”, “three”) numbers[1] = “two” numbers.set(2,””) println(numbers)
val numbers = mutableListOf(1, 2, 3, 4)
numbers.fill(3)
println(numbers)
//删除
val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.removeAt(1)
numbers.removeFirst()
numbers.removeLast()
println(numbers)
- set的相关操作, 并集用union(),交集用intersect(),差集用subtract()
```kotlin
val numbers = setOf("one", "two", "three")
println(numbers union setOf("four", "five"))
println(setOf("four", "five") union numbers)
println(numbers intersect setOf("two", "one"))
println(numbers subtract setOf("three", "four"))
println(numbers subtract setOf("four", "three")) // 相同的输出
Map的相关操作
取键和值
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3) println(numbersMap.get("one")) println(numbersMap["one"]) println(numbersMap.getOrDefault("four", 10)) println(numbersMap["five"]) // null //numbersMap.getValue("six") // exception!过滤
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11) val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10} println(filteredMap) //filter传递的是pair参数,而分别对键和值进行检查的是filterKeys(),filterValues() val filteredKeysMap = numbersMap.filterKeys { it.endsWith("1") } val filteredValuesMap = numbersMap.filterValues { it < 10 }plus和minus操作
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3) println(numbersMap + Pair("four", 4)) println(numbersMap + Pair("one", 10)) println(numbersMap + mapOf("five" to 5, "one" to 11)) println(numbersMap - "one") println(numbersMap - listOf("two", "four"))添加,更新条目
val numbersMap = mutableMapOf("one" to 1, "two" to 2) numbersMap.put("three", 3) numbersMap.putAll(setOf("four" to 4, "five" to 5))删除条目
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3) numbersMap.remove("one") println(numbersMap) numbersMap.remove("three", 4) //不会删除任何条目 numbersMap.remove("three", 3) println(numbersMap)
