前置知识: Java

Kotlin 集合与协程

00:00
2 min Intermediate 2026/6/14

集合框架、序列、集合操作函数与协程基础。

1. 集合框架

Kotlin 集合框架分为只读可变两大体系:

1.1 集合类型

类型只读可变描述
ListList<T>MutableList<T>有序可重复
SetSet<T>MutableSet<T>无序不重复
MapMap<K, V>MutableMap<K, V>键值对
// 只读集合
val list: List<String> = listOf("a", "b", "c")
val set: Set<Int> = setOf(1, 2, 3)
val map: Map<String, Int> = mapOf("a" to 1, "b" to 2)

// 可变集合
val mutableList: MutableList<String> = mutableListOf("a", "b")
val mutableSet: MutableSet<Int> = mutableSetOf(1, 2)
val mutableMap: MutableMap<String, Int> = mutableMapOf("a" to 1)

// 只读视图
val readOnly: List<String> = mutableList.toList()  // 创建副本
val readOnlyView: List<String> = mutableList       // 仅类型约束,底层数据共享

1.2 List 操作

val list = listOf("apple", "banana", "cherry", "date")

// 访问元素
list[0]                  // "apple"
list.getOrNull(10)       // null(安全访问)
list.first()             // "apple"
list.last()              // "date"
list.firstOrNull { it.startsWith("b") }  // "banana"

// 子列表
list.subList(1, 3)       // ["banana", "cherry"]

// 查找
list.indexOf("cherry")   // 2
list.binarySearch("cherry")  // 二分查找(需排序)

// 切片
list.slice(1..2)         // ["banana", "cherry"]
list.slice(setOf(0, 3))  // ["apple", "date"]

1.3 Set 操作

val set1 = setOf(1, 2, 3, 4)
val set2 = setOf(3, 4, 5, 6)

// 集合运算
set1 union set2          // {1, 2, 3, 4, 5, 6} 并集
set1 intersect set2      // {3, 4} 交集
set1 subtract set2       // {1, 2} 差集

// 包含检查
set1.contains(3)         // true
3 in set1                // true
set1.containsAll(setOf(1, 2))  // true

1.4 Map 操作

val map = mapOf("a" to 1, "b" to 2, "c" to 3)

// 访问
map["a"]                 // 1
map.getValue("a")        // 1(不存在则抛异常)
map.getOrDefault("d", 0) // 0
map.getOrElse("d") { 0 } // 0

// 遍历
for ((key, value) in map) {
    println("$key = $value")
}

// 常用操作
map.keys                 // [a, b, c]
map.values               // [1, 2, 3]
map.entries              // [a=1, b=2, c=3]

// 可变 Map 操作
val mutableMap = mutableMapOf("a" to 1)
mutableMap["b"] = 2
mutableMap.putIfAbsent("c", 3)
mutableMap.remove("a")
mutableMap += "d" to 4

2. 序列(Sequence)

序列惰性求值集合类似 Java Stream,但适用于所有平台

2.1 创建序列

// 从集合创建
val seq = listOf(1, 2, 3).asSequence()

// 使用 generateSequence
val naturalNumbers = generateSequence(1) { it + 1 }
val first10 = naturalNumbers.take(10).toList()  // [1, 2, ..., 10]

// 使用 sequence 构建器
val fibonacci = sequence {
    var a = 0L
    var b = 1L
    while (true) {
        yield(a)
        val next = a + b
        a = b
        b = next
    }
}
fibonacci.take(10).toList()  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

2.2 惰性求值 vs 及早求值

// List — 及早求值(每个操作都创建新集合)
val listResult = (1..1000)
    .map { println("map $it"); it * 2 }
    .filter { println("filter $it"); it > 10 }
    .first()
// 输出:map 1, filter 2, map 2, filter 4, ... map 6, filter 12 → 返回 12
// 执行了 6 次 map + 6 次 filter

// Sequence — 惰性求值(逐元素处理管道)
val seqResult = (1..1000).asSequence()
    .map { println("map $it"); it * 2 }
    .filter { println("filter $it"); it > 10 }
    .first()
// 输出:map 1, filter 2, map 2, filter 4, map 3, filter 6, map 4, filter 8, map 5, filter 10, map 6, filter 12
// 同样找到 12,但只处理了必要的元素

何时使用 Sequence:当集合较大且链式操作时,Sequence显著减少中间集合创建和计算量。

3. 集合操作函数

3.1 过滤与映射

val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 过滤
numbers.filter { it > 5 }              // [6, 7, 8, 9, 10]
numbers.filterNot { it > 5 }           // [1, 2, 3, 4, 5]
numbers.filterIndexed { i, v -> i > 3 && v > 5 }  // [6, 7, 8, 9, 10]
numbers.partition { it > 5 }           // ([6,7,8,9,10], [1,2,3,4,5])

// 映射
numbers.map { it * 2 }                 // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
numbers.mapIndexed { i, v -> "$i:$v" } // ["0:1", "1:2", ...]
numbers.mapNotNull { if (it > 5) it else null }  // [6, 7, 8, 9, 10]

// flatMap — 映射后展平
val words = listOf("Hello", "Kotlin")
words.flatMap { it.toList() }          // [H, e, l, l, o, K, o, t, l, i, n]

3.2 排序

val list = listOf(3, 1, 4, 1, 5, 9, 2, 6)

list.sorted()                          // [1, 1, 2, 3, 4, 5, 6, 9]
list.sortedDescending()                // [9, 6, 5, 4, 3, 2, 1, 1]
list.sortedBy { it % 3 }              // 按模 3 排序
list.sortedWith(compareBy({ it % 3 }, { it }))  // 多条件排序

// 原地排序(MutableList)
val mutable = mutableListOf(3, 1, 4, 1, 5)
mutable.sort()

3.3 聚合

val list = listOf(1, 2, 3, 4, 5)

list.sum()                             // 15
list.sumOf { it * 2 }                  // 30
list.average()                         // 3.0
list.count()                           // 5
list.count { it > 3 }                  // 2
list.minOrNull()                       // 1
list.maxOrNull()                       // 5
list.minByOrNull { it }                // 1

// reduce — 从左到右累积
list.reduce { acc, num -> acc + num }  // 15

// fold — 带初始值的累积
list.fold(0) { acc, num -> acc + num } // 15
list.fold(1) { acc, num -> acc * num } // 120

// groupBy — 分组
val words = listOf("a", "ab", "abc", "bc", "c")
words.groupBy { it.length }
// {1=[a, c], 2=[ab, bc], 3=[abc]}

// associate — 转换为 Map
list.associateBy { "key$it" }          // {key1=1, key2=2, ...}
list.associateWith { it * 10 }         // {1=10, 2=20, ...}

3.4 查找

val list = listOf(1, 2, 3, 4, 5)

list.find { it > 3 }                   // 4(第一个匹配)
list.findLast { it > 3 }               // 5(最后一个匹配)
list.first { it > 3 }                  // 4(不存在则抛异常)
list.any { it > 3 }                    // true
list.none { it > 10 }                  // true
list.all { it > 0 }                    // true

4. 协程基础

协程是 Kotlin 的轻量级线程,提供结构化并发的编程模型。

4.1 添加依赖

// build.gradle.kts
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1")
    // Android
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1")
}

4.2 第一个协程

import kotlinx.coroutines.*

fun main() = runBlocking {  // 桥接协程与阻塞世界
    launch {  // 启动新协程
        delay(1000L)  // 非阻塞等待
        println("World!")
    }
    println("Hello")
}
// 输出:Hello → (1秒后) World!

4.3 suspend 函数

suspend fun fetchData(): String {
    delay(1000)  // 模拟网络请求
    return "Data from network"
}

suspend fun processAll() {
    val data = fetchData()  // 在协程中调用 suspend 函数
    println(data)
}

4.4 协程构建器

// launch — 启动协程,不返回结果(返回 Job)
val job: Job = scope.launch {
    delay(1000)
    println("Done")
}

// async — 启动协程,返回结果(返回 Deferred<T>)
val deferred: Deferred<Int> = scope.async {
    delay(1000)
    42
}
val result = deferred.await()  // 等待结果

// 并行执行
suspend fun fetchBoth(): Pair<String, String> = coroutineScope {
    val deferred1 = async { fetchUser() }
    val deferred2 = async { fetchOrders() }
    Pair(deferred1.await(), deferred2.await())
}

4.5 协程作用域

// coroutineScope — 等待所有子协程完成
suspend fun fetchAll() = coroutineScope {
    launch { fetchUser() }
    launch { fetchOrders() }
    // 两个 launch 都完成后才返回
}

// supervisorScope — 子协程失败不影响其他子协程
suspend fun fetchWithRecovery() = supervisorScope {
    launch {
        throw Exception("Failed")  // 不影响另一个
    }
    launch {
        delay(100)
        println("This still runs")
    }
}

4.6 调度器

// Dispatchers.Default — CPU 密集型任务
launch(Dispatchers.Default) {
    val result = heavyComputation()
}

// Dispatchers.IO — IO 密集型任务
launch(Dispatchers.IO) {
    val data = networkRequest()
}

// Dispatchers.Main — UI 线程(Android/Swing)
launch(Dispatchers.Main) {
    updateUI(result)
}

// withContext — 切换调度器
suspend fun fetchAndShow() {
    val data = withContext(Dispatchers.IO) {
        networkRequest()  // 在 IO 线程执行
    }
    showData(data)  // 回到原调度器
}

5. Flow

Flow 是 Kotlin 协程响应式流 API,类似 RxJava 但基于协程

5.1 创建 Flow

// flow 构建器
fun numbers(): Flow<Int> = flow {
    for (i in 1..5) {
        emit(i)  // 发射值
        delay(100)
    }
}

// flowOf
val flow = flowOf(1, 2, 3, 4, 5)

// 从集合转换
val listFlow = listOf(1, 2, 3).asFlow()

// channelFlow — 支持并发发射
fun mergedFlow(): Flow<Int> = channelFlow {
    launch { send(1) }
    launch { send(2) }
}

5.2 收集 Flow

// collect — 终端操作
numbers().collect { value ->
    println(value)
}

// toList — 转为列表
val list = numbers().toList()

// first / firstOrNull
val first = numbers().first()

// collectLatest — 只处理最新值
numbers().collectLatest { value ->
    delay(200)  // 模拟慢处理
    println(value)  // 只打印最后一个
}

5.3 Flow 操作符

numbers()
    .map { it * 2 }              // 变换
    .filter { it > 4 }           // 过滤
    .take(3)                     // 取前 3 个
    .drop(1)                     // 跳过第 1 个
    .distinctUntilChanged()      // 去重
    .onEach { println("Emit: $it") }  // 副作用
    .onStart { emit(0) }         // 开始前发射
    .onCompletion { println("Done") }  // 完成回调
    .catch { e -> emit(-1) }     // 错误处理
    .collect { println(it) }

6. Channel

Channel协程通信管道类似 BlockingQueue

val channel = Channel<Int>()

// 生产者
launch {
    for (i in 1..5) {
        channel.send(i)
    }
    channel.close()
}

// 消费者
launch {
    for (value in channel) {
        println(value)
    }
}

// produce — 便捷生产者
fun produceNumbers(): ReceiveChannel<Int> = GlobalScope.produce {
    for (i in 1..5) {
        send(i)
    }
}

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式