一、概念
1.1 继承关系

只读接口提供访问元素的操作,可变接口通过扩展只读接口提供变更元素的操作。
1.2 集合区别
| 元素不可变(只读) | 元素可变(增删改) | |
| 有序(有索引,元素可以重复) | List<E> | MutableList<E> |
| 无序(无索引,元素不可重复) | Set<E> | MutableSet<E> |
| 键值对(key具有唯一性) | Map<K, V> | MutableMap<K, V> |
1.3 集合类型的协变
当一个集合赋值给另一个集合,或者可变集合与不可变集合互转的时候,如果集合类型不相同,子类可以赋值给父类。例如 List<Son> 可以赋值给 List<Father>,List<Son>可以 .toMutableList() 转为 List<Father>。
1.4 更高效的处理元素
在集合上链式调用多个操作(如 map + filter + flatMap)时,会产生中间集合,带来额外内存开销。若操作较复杂或数据量较大,推荐使用 asSequence() 转为惰性序列,以减少中间产物,提升性能。详见:序列Sequence
二、创建
2.1 List
元素是有序的,可以重复,因为该类型具备索引。底层使用的是ArrayList。
| 由元素构造 | public inline fun <T> listOf(): List<T> = emptyList() public inline fun <T> mutableListOf(): MutableList<T> = ArrayList() 创建空集合。 |
| public fun <T> listOf(vararg elements: T): List<T> public fun <T> mutableListOf(vararg elements: T): MutableList<T> 通过指定元素创建集合。 | |
| 空集合 | public fun <T> emptyList(): List<T> 创建空List。 |
| 工厂函数 | public inline fun <T> List(size: Int, init: (index: Int) -> T): List<T> public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> 参数size是指定大小, 参数init是每个元素的初始化方式。 |
| 构建器函数 | public inline fun <E> buildList(builderAction: MutableList<E>.() -> Unit): List<E> public inline fun <E> buildList(capacity: Int, @BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> 参数initialCapacity是指定大小,参数builderAction是每个元素的初始化方式。作用域中调用的是 MutableList 的方法,最后返回的是一个 List。 |
| 具体类型的集合 | public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList() Kotlin有自己包装过的ArrayList(不推荐,Kotlin的List底层就是由它实现的)。 |
| public LinkedList() 通过 Java 构造函数创建 LinkedList。 | |
| 避免装箱开销 | public fun intListOf(): IntList = EmptyIntList public inline fun mutableIntListOf(): MutableIntList = MutableIntList() public fun emptyIntList(): IntList = EmptyIntList 空集合。 通过指定元素创建集合。 构建器函数。 非线程安全,且遍历中修改可能引发问题,总之别用就行。同理还有 Long、Double、Float。 |
val list1 = listOf(1,"哈哈",false) //自动类型推断
val list2 = listOf<String>("你","我","他") //声明确定类型
val list3 = buildList {
add(1)
add(2)
add(3)
}
val linkedList1 = LinkedList<Int>(listOf(1,2,3)) //类型是 LinkedList<Int>
val linkedList2 = LinkedList(listOf(1,2,3)) //类型是 LinkedList<Int!>
2.2 Set
元素是无序的,不可以重复(任意两个元素 hashCode() 和 equals() 都不相等),存入和取出的顺序不一定相同。底层使用的是LinkedHashSet,当元素个数 N<3,初始容量为 N+1当元素个数 N<最大值/2+1,初始容量为 N+N/3,否则初始容量为 2147483647。
| 由元素构造 | public inline fun <T> setOf(): Set<T> = emptySet() public inline fun <T> mutableSetOf(): MutableSet<T> = LinkedHashSet() 创建空集合。 |
| 空集合 | public fun <T> emptySet(): Set<T> = EmptySet 创建空Set。 |
| 构建器函数 | public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> public inline fun <E> buildSet(capacity: Int, @BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> |
| 具体类型的集合 | public inline fun <T> linkedSetOf(): LinkedHashSet<T> = LinkedHashSet() public fun <T> linkedSetOf(vararg elements: T): LinkedHashSet<T> |
| public inline fun <T> hashSetOf(): HashSet<T> = HashSet() public fun <T> hashSetOf(vararg elements: T): HashSet<T> | |
| public fun <T> sortedSetOf(vararg elements: T): java.util.TreeSet<T> public fun <T> sortedSetOf(comparator: Comparator<in T>, vararg elements: T): java.util.TreeSet<T> |
val ss = mutableSetOf (1,3,5,7 )
ss + 9 // [1,3,5,7,9]
ss - listOf (1,3) // [5,7]
2.3 集合字面量 Collection Literals
v2.4.0-Bare2 引入,目前处于实验性。20260610
通过方括号简洁创建集合,编译器会把方括号转换为对目标类型伴生对象上 operator fun of() 方法的调用。默认创建 List 类型,MutableList、Set、MutableSet 需要显示声明属性类型,不能把目标类型设成 Java 定义的集合类型。
- Map 字面量:["key": 1] 目前还不存在。三个原因:Java 互操作痛点、装箱性能,以及 Map.Entry 是接口带来的尴尬。语法空间会先保留,也许未来再交付。
- Tuple 字面量:Pair 和 Triple 不能通过方括号触达,部分原因是 operator fun of() 的形状无法在单个 vararg 中表达异构类型。
- 没有期望类型的空字面量:val x = [] 会编译失败,原因和 emptyList() 返回 List<T> 而不是 List<Nothing> 类似。
2.3.1 基本使用
// 显式类型声明
val shapes: MutableList<String> = ["triangle", "square", "circle"]
// 无声明默认创建 List
val fruit = ["apple", "banana", "cherry"]
if (countryCode in ["US", "CA", "MX"]) {
...
}
2.3.2 自定义容器
这个机制是开放的,任何类型只要在伴生对象上提供格式正确的 operator fun of() 就可以使用方括号。
目前处于实验性
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xcollection-literals")
}
}
这两个 of 重载是合法的,因为它们只在参数数量上不同,而且 vararg rest 前面的每个参数都和 rest 本身拥有相同类型。这样写,能强迫你必须创建一个非空的容器,因为你不能 [] 这么写,这是个非常值得学习的小技巧。两个重载必须返回相同类型,并且拥有相同可见性。
// 定义
class NonEmptyList<T> private constructor(
val head: T,
val tail: List<T>,
) {
val size: Int get() = 1 + tail.size
fun toList(): List<T> = listOf(head) + tail
companion object {
operator fun <T> of(first: T): NonEmptyList<T> =
NonEmptyList(first, emptyList())
operator fun <T> of(first: T, vararg rest: T): NonEmptyList<T> =
NonEmptyList(first, rest.toList())
}
}
// 使用
val onboarding: NonEmptyList<OnboardingStep> = [
OnboardingStep.Welcome,
OnboardingStep.PermissionsRequest,
OnboardingStep.AccountLinking,
]
当期望类型本身也支持方括号时,可以嵌套使用。在矩阵式或网格式数据中,这种写法能带来可读性提升。
// 定义
class DoubleMatrix(vararg val rows: Row) {
companion object {
operator fun of(vararg rows: Row) = DoubleMatrix(*rows)
}
}
class Row(vararg val elements: Double) {
companion object {
operator fun of(vararg elements: Double) = Row(*elements)
}
}
// 使用
val identityMatrix: DoubleMatrix = [
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
]
三、转换
| toList () toMutableList () toSet () toMutableSet () | 转换为 List 集合,有序 转换为 Set 集合,去重 转换为 Mutable***元素可变集合 |
| associate () associateBy () | 转换为 Map |
| to***Array () | 转换为基本类型数组 |
四、合并
| plus (元素/数组/集合/序列) minus (元素/数组/集合/序列) numusElement (元素) | plus(T):List<T> plus(Iterable<T>):List<T> plus(Array<out T>):List<T> plus(Sequence<T>):List<T> 往集合中添加一个元素/数组/集合/序列,返回一个新集合不会修改原集合,推荐使用操作符 “+” |
| minus(T):List<T> minus(Iterable<T>):List<T> minus(Array<out T>):List<T> minus(Sequence<T>):List<T> 往集合中删除一个元素/数组/集合/序列,返回一个新集合,推荐使用操作符 “-” | |
| plusElement(T):List<T> 同上,底层使用的 plus(T) | |
| minusElement(T):List<T> 同上,底层使用的 minus(T) |
val list1 = listOf(1,2,3)
val list2 = listOf(7,8)
val list3 = list1 + 4 //返回的是一个新集合,不会修改原集合list1,[1,2,3,4]
val list4 = list1.plus(list2)//返回的是一个新集合,不会修改原集合list1,[1,2,3,7,8]
五、获取
5.1 根据索引获取元素
| get (索引) getOrElse (索引,默认值) getOrNull (索引) elementAt (索引) elementAtOrElse (索引,默认值) elementAtOrNull (索引) | get(Int):T 获取该索引位置上的元素,没有则报错,推荐使用运算符 [ ] |
| getOrElse(Int,Int -> T):T 获取该索引位置上的元素,没有则返回默认值 | |
| getOrNull(int):T? 获取该索引位置上的元素,没有则返回 null | |
| elementAt(Int):T 获取该索引位置上的元素,没有则报错,推荐使用运算符 [ ] | |
| elementAtOrElse(Int,Int -> T):T 获取该索引位置上的元素,没有则返回默认值 | |
| elementAtOrNull(Int):T? 获取该索引位置上的元素,没有则返回 null |
5.2 根据元素获取索引
| indexOf (元素) indexOfFrist (条件) indexOfLast (条件) lastIndexOf (元素) | indexOf(T):Int 获取该元素在List中对应的索引,没有则返回-1 |
| indexOfFrist(T -> Boolean):Int 获取第一个符合条件的元素索引,没有则返回-1 | |
| indexOfLast(T -> Boolean):Int 获取最后一个符合条件的元素索引,没有则返回-1 | |
| lastIndexOf (T):Int 获取该元素最后一次出现的索引,没有则返回-1 |
5.3 首尾元素
| frist () frist (predicate) fristOrNull () fristOrNull (predicate) last () last (predicate) lastOrNull () lastorNull (predicate) find () findLast () | frist():T 获取第一个元素,没有则报错 |
| frist(T ->Boolean):T 获取第一个符合条件的元素,没有则抛异常 | |
| fristOrNull():T? 获取第一个元素,没有则返回 null | |
| fristOrNull(T ->Boolean):T? 获取符合条件的第一个元素,没有则返回 null | |
| last():T 获取最后一个元素,没有则报错 | |
| last(T -> Boolean):T 获取最后一个符合条件的元素,没有则抛异常 | |
| lastOrNull():T? 获取最后一个元素,没有则返回 null | |
| lastOrNull(T -> Boolean):T? 获取符合条件的最后一个元素,没有则返回 null | |
| find(T -> Boolean):T 同理 frist(),获取第一个符合条件的元素,没有则抛异常 | |
| 同理 lastOrNull (),获取符合条件的最后一个元素,没有则返回 null |
5.4 唯一元素
| single () single (predicate) singleOrNull () | single() 集合只能且必须包含一个元素,并返回该元素,否则报错 |
| single(T -> Boolean):T 集合只能且必须包含一个符合条件的元素,并返回该元素,否则报错 | |
| singOrNull():T? 集合只能且必须包含一个符合条件的元素,并返回该元素,否则返回 null |
5.5 平均值
| average () | average ():T 获取所有元素的平均值(元素之和/元素数量,仅限数值类型) |
5.6 最值
| min () minBy (function(索引)) : T max () maxBy (function(索引)) : T | min():T? 返回集合中最小值的元素,空集返回 null |
| minBy(T -> R):T? 根据条件,返回集合中最小值的元素,空集返回 null。比较的是运算后的R,但返回的是元素T | |
| max():T? 返回集合中最大值的元素,空集返回 null | |
| maxBy(T -> R):T? 根据条件,返回集合中最小值的元素,空集返回 null。比较的是运算后的R,但返回的是元素T |
六、查询
| count () count (predicate) | count():Int 集合中元素的个数 |
| count(T -> Boolean):Int 集合中满足条件的元素个数 | |
| min () minBy (function(索引)) : T max () maxBy (function(索引)) : T | min():T? 返回集合中最小值的元素,空集返回 null |
| minBy(T -> R):T? 根据条件,返回集合中最小值的元素,空集返回 null。比较的是运算后的R,但返回的是元素T | |
| max():T? 返回集合中最大值的元素,空集返回 null | |
| maxBy(T -> R):T? 根据条件,返回集合中最小值的元素,空集返回 null。比较的是运算后的R,但返回的是元素T | |
| contains (元素) containsAll (集合) | contains(T):Boolean 集合中是否包含该元素,包含返回true |
| contains(Collection):Boolean 集合中是否包含该子集,包含返回true | |
| any () any (条件) all (条件) none () none (条件) | any():Boolean 集合中是否至少有一个元素 |
| any(T -> Boolean):Boolean 集合中是否至少有一个元素满足条件 | |
| all(T -> Boolean):Boolean 集合中是否所有元素都满足条件 | |
| none():Boolean 集合中是否没有元素 | |
| none(T -> Boolean):Boolean 集合中是否没有元素满足条件 |
6.1 元素个数(集合大小)
| size count () count (条件) | count():Int 集合中元素的个数 |
| count(T -> Boolean):Int 集合中满足条件的元素个数 |
6.2 是否包含某元素
| contains (元素) containsAll (集合) | contains(T):Boolean 集合中是否包含该元素,包含返回true |
| contains(Collection):Boolean 集合中是否包含该子集,包含返回true |
6.3 满足条件
6.3.1 是否有元素满足条件
| any () any (条件) | any():Boolean 集合中是否至少有一个元素 |
| any(T -> Boolean):Boolean 集合中是否至少有一个元素满足条件 |
6.3.2 是否元素全部满足条件
| all (条件) | all(T -> Boolean):Boolean 集合中是否所有元素都满足条件 |
6.3.3 是否没有元素满足条件
| none () none (条件) | none():Boolean 集合中是否没有元素 |
| none(T -> Boolean):Boolean 集合中是否没有元素满足条件 |
6.4 是否有序
v2.4.0 开始支持。如果元素按指定顺序排列,或者元素少于两个,它们将返回 true,否则返回 false。这些函数在遇到无序对时会立即停止,这使得它们对大型输入非常高效。
| isSorted() isSortedDescending() isSortedWith(比较器) isSortedBy(条件) isSortedByDescending(条件) | public fun <T : Comparable<T>> Iterable<T>.isSorted(): Boolean |
| public fun <T : Comparable<T>> Iterable<T>.isSortedDescending(): Boolean | |
| public fun <T> Iterable<T>.isSortedWith(comparator: Comparator<in T>): Boolean | |
| public inline fun <T, R : Comparable<R>> Iterable<T>.isSortedBy(selector: (T) -> R?): Boolean | |
| public inline fun <T, R : Comparable<R>> Iterable<T>.isSortedByDescending(selector: (T) -> R?): Boolean |
七、子集
7.1 从区间截取
| slice (区间) slice (集合) | slice(IntRange):List<T> 截取该索引区间的元素,返回一个子List |
| slice(Iterable<Int>):List<T> 返回一个子List,所包含的 element 是传入 Iterable 的 element 当作 index 对应的 element |
7.2 从头或从尾开始截取
| take (数量) takeLast (数量) takeWhile (predicate) takeLastWhile (predicate) | take(Int):List<T> 截取前 N 个元素,返回一个子集合,N=0返回空集,N>size返回该集合,N<0报错 |
| takeLast(Int):List<T> 截取后 N 个元素,返回一个子集合,N=0返回空集,N>size返回该集合,N<0报错 | |
| takeWhile(T -> Boolean):List<T> 正序,返回一个满足条件元素的子集合,遇到不满足条件就停止 | |
| takeLastWhile(T -> Boolean):List<T> 倒序,返回一个满足条件元素的子集合,遇到不满足条件就停止 |
7.3 从头或从尾开始去除
| drop (数量) dropLast (数量) dropWhile (predicate) dropLastWhile (predicate) | drop(Int):List<T> 去除前 N 个元素,返回一个包含剩下元素的子集合,N=0返回该集合,N>size返回空集,N<0报错 |
| dropLast(Int):List<T> 去除后 N 个元素,返回一个包含剩下元素的子集合,N=0返回该集合,N>size返回空集,N<0报错 | |
| dropWhile(T -> Boolean):List<T> 正序,去除满足条件的元素,返回一个包含剩下元素的子集合,遇到不满足条件就停止 | |
| dropLastWhile(T -> Boolean):List<T> 倒序,去除满足条件的元素,返回一个包含剩下元素的子集合,遇到不满足条件就停止 |
7.4 去重
| distinct () distinctBy (function) | distinct():List<T> 去除重复元素(会保留第一次出现的)。 |
| distinctBy(T -> K):List<T> 去除集合中的重复给定元素(会保留第一次出现的)。 |
7.5 过滤
| filter (predicate) filterIndexed (predicate(索引,元素)) filterNot (predicate) filterNotNull (predicate) filterTo (子集合,predicate) | filter(T -> Boolean):List<T> 返回一个包含满足条件元素的子集合 |
| 同上,多了索引可使用 | |
| filterNot(T -> Boolean):List<T> 返回一个包含不满足条件元素的子集合??????? | |
| filterNotNull(T -> Boolean):List<T> 返回一个不包含null元素的子集合??????? | |
| filterTo(MutableCollection,T -> Boolean):MutableCollection 用传入的子集合 MutableCollection 去装满足条件的 element,并返回子集合 |
八、排序
8.1 条件排序
| sorted () sortedDescending () sortedBy (function) sortedDescendingBy (function(元素)) | sorted():List<T> 将集合中的元素按照自然排序进行升序排列 |
| sortedDescending():List<T> 将集合中的元素按照自然排序进行降序排列 | |
| sortedBy(T -> R?):Unit 根据函数对集合中的 element 进行计算,按结果进行升序排列,结果类型要实现Comparable | |
| sortedDescendingBy(T -> R?):Unit 根据函数对集合中的 element 进行计算,按结果进行降序排列,结果类型要实现Comparable |
8.2 反转顺序
| reversed () | reversed():List<T> 反转集合中的元素,返回一个新集合 |
九、运算
9.1 累加
| sumOf ( 元素 -> 累加值 ) | sumOf(T -> Int):Int 对元素挨个进行累加计算,初始值为0 |
9.2 规约
| reduce ( (累加值,下一个元素) -> 累加值 ) reduceRight ( (下一个元素,累加值) -> 累加值 ) fold ( 初始值,(累加值,下一个元素) -> 累加值 ) foldRight ( 初始值, (下一个元素, 累加值) -> 累加值 ) | reduce( (S,T) -> S):S 根据给定的函数,正序对元素挨个进行运算 |
| reduceRight( (T,S) -> S):S 根据给定的函数,倒序对元素挨个进行运算 | |
| fold(R,(R,T) -> R):R 带初始值的 reduce | |
| foldRight(R,(T,R) -> R):R 带初始值的 reduceRight |
十、映射(新集)
10.1 转成 List
| map (function(元素)) mapIndexed (function(索引,元素)->新值) mapNotNull (function(元素)) | map(T -> R):List<R> 通过函数对元素进行运算,返回一个包含运算后元素的新集合。 T元素,R运算后的值 |
| mapIndexed( (Int,T) -> R):List<R> 通过函数对元素进行运算,返回一个包含运算后元素的新集合,多了一个索引可使用 | |
| 通过函数对元素进行运算,返回一个包含运算后元素的新集合,会去掉null元素 |
10.2 转成 List<List>
| windowed() | |
| chunked() |
val numbers = (1..5).toList()
println(numbers.windowed(3)) // [[1,2,3],[2,3,4],[3,4,5]]
println(numbers.chunked(2)) // [[1,2],[3,4],[5]]
10.3 转成 Map
| groupBy (T -> 键): Map(键, List<T>) groupBy (T -> 键,T -> 值): Map<键,值> groupBy (T -> 值): Grouping<T,值> | groupBy(T -> K):Map<K,list<T> > 对 element 进行运算,结果当作 key,相同结果的 element 为一组 List 当作 Value |
| groupBy (T -> K,T -> V): Map<K,V> 对 element 进行运算,第一个运算结果当作 Key,第二个运算结果当作 Value | |
| groupBy(T -> K): Grouping<T,K> |
10.4 转成 List<Pair>
| zip (集合2): List<Pair<集合1元素, 集合2元素>> | zip(Iterable<R>):List<Pait<T,R>> 对两个集合进行配对,相同 index 的两个 element 存入 Pair,作为返回的新List 的 element |
10.5 转成 Pair
| partition (predicate): Pair<List1包含所有满足条件的元素,List2包含所有不满足条件的元素> | partition(T -> Boolean):Pair<List<T>,List<T>> 根据条件,将集合拆成2个子集合组成的Pair,满足条件的在左边 |
十一、遍历
11.1 遍历
| forEach (元素 -> Unit) | forEach(T -> Unit):Unit 遍历 |
| forEachIndexed ( (索引,元素) -> Unit ) | forEachIndexed( (Int,T) -> Unit):Unit 带索引遍历,Int是索引,T是元素 |
| onEach() | 对每个元素执行操作 |
(1..5).map { it * 2}.onEach { println(it) }.toList()
11.2 展平
| flatten () flatMap (function(元素)) | 遍历集合中的元素,元素包含子元素也遍历。 |
| flatMap(T -> Iterable<R>):List<R> 展平后再进行映射。 |
val nested = listOf(listOf(1,2), listOf(3,4))
val flat = nested.flatten() // [1,2,3,4]
val flatDoubled = nested.flatMap { it.map { it*2 } } // [2,4,6,8]
十二、MutableList
| toList () | 转换为 List 元素不可变集合 |
| add (元素) add (索引,元素) addAll (子集合) addAll (索引,子集合) | add(E):Boolean 在集合尾部添加新元素,成功则返回true |
| add(Int,E):Boolean 往该索引位置上插入新元素,索引不存在则报错 | |
| addAll(Collection<E>):Boolean 添加子集合,成功则返回true | |
| addAll(Int,Collection<E>):Boolean 往该索引位置上插入子集合,成功则返回true | |
| remove (元素) removeAt (索引) removeAll (子集合) | remove(E):Boolean 删除集合中第一次出现的该元素,成功则返回true |
| removeAt(Int):E 删除该索引位置上的元素,索引不存在则报错 | |
| removeAll(Collection<E>):Boolean 删除子集合,成功则返回true | |
| set (索引,元素) | set(Int,E):E 对该索引上的元素赋值 |
| clear () | clear():Unit 清空集合中的元素 |
| retainAll (另一个集合) | retainAll(Collection<E>):Boolean 取交集:只保留两个集合都有的元素,成功则返回true |
本文主要介绍Kotlin中集合Collection里的List和Set。阐述了集合的概念,包括继承关系、集合区别和类型协变;说明了List和Set的创建特点,如List有序可重复,Set无序不可重复;还提及了集合操作符,如转换、增删、获取等,最后提到了MutableList。
5411

被折叠的 条评论
为什么被折叠?



