Edit Page

集合操作概述

最终更新: 2024/03/21

Kotlin 标准库提供了大量的函数用来在集合上进行各种操作. 包括简单的操作, 比如获取元素, 添加元素, 以及更复杂的操作, 比如查找, 排序, 过滤(Filtering), 变换(Transformation), 等等.

扩展函数与成员函数

标准库中定义的操作有两类: 集合接口的 成员函数, 以及 扩展函数.

成员函数定义了的集合类型的基本操作. 比如, Collection 包含函数 isEmpty() 用来检查集合是否为空; List 包含 get() 函数, 用于按下标访问元素, 等等.

当你自己实现集合接口时, 你必须实现集合的成员函数. 为了更简单地实现集合, 你可以使用标准库中集合接口的框架实现类: AbstractCollection, AbstractList, AbstractSet, AbstractMap, 以及与它们对应的可变集合类.

其他集合操作声明为扩展函数. 包括过滤, 变换, 排序, 以及其他的集合处理函数.

共通操作

共通操作对 只读和可变集合 都有效. 共通操作包括以下几组:

这些章节中介绍的集合操作返回的结果不会影响原来的集合. 比如, 过滤操作会产生一个 新集合, 其中包含符合过滤条件的所有元素. 因此, 这些操作的结果需要保存在变量中, 或者通过其他方式使用, 比如作为参数传递给其他函数.


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")  
    numbers.filter { it.length > 3 }  // `numbers` 不会受影响, 过滤结果会丢失
    println("numbers are still $numbers")
    val longerThan3 = numbers.filter { it.length > 3 } // 过滤结果保存在变量 `longerThan3` 中
    println("numbers longer than 3 chars are $longerThan3")
//sampleEnd
}

对某些集合操作, 可以指定 目标 对象. 这里的目标集合是一个可变的集合, 集合操作函数会将结果添加到目标集合中, 而不是创建新的集合作为返回值. 要使用目标集合来进行操作, 需要使用其他函数, 函数名带有 To 后缀, 比如, 要使用 filterTo() 而不是 filter(), 或者使用 associateTo() 而不是 associate(). 这些函数接受一个额外的参数来指定目标集合.


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    val filterResults = mutableListOf<String>()  // 目标集合
    numbers.filterTo(filterResults) { it.length > 3 }
    numbers.filterIndexedTo(filterResults) { index, _ -> index == 0 }
    println(filterResults) // 目标集合中包含两次操作的全部结果
//sampleEnd
}

为了方便使用, 这些函数会将目标集合作为返回值, 因此你可以在调用这些函数的参数中直接创建目标函数的实例:


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    // 过滤 numbers, 结果直接保存到一个新创建的 hash set,
    // 因此, 结果中重复的数字会被删除
    val result = numbers.mapTo(HashSet()) { it.length }
    println("distinct item lengths are $result")
//sampleEnd
}

带目标集合的函数可以用来执行过滤, 关联(associate), 分组, 压扁(flatten), 以及其他操作. 关于带目标集合的所有操作, 请参见 Kotlin 集合 API 文档.

写入操作

对于可变的集合, 还有 写操作 可以改变集合的状态. 这类写操作包括添加元素, 删除元素, 以及变更元素. 关于写入操作的详情, 请参见 集合写入操作, 以及 List 相关操作Set 相关操作 中对应的章节.

对于特定的写入操作, 存在一对函数用来执行相同的操作: 一个函数直接在原来的集合上进行变更, 另一个则将变更后的结果作为新的集合返回, 而不影响原来的集合. 比如, sort() 函数直接对一个可变集合进行排序, 因此集合状态会发生变化; 而 sorted() 函数则会创建一个新的集合, 其中包含相同的元素排序后的结果, 而原来的集合不会变化.


fun main() {
//sampleStart
    val numbers = mutableListOf("one", "two", "three", "four")
    val sortedNumbers = numbers.sorted()
    println(numbers == sortedNumbers)  // 结果为 false
    numbers.sort()
    println(numbers == sortedNumbers)  // 结果为 true
//sampleEnd
}