Kotlin 序列 #
一、序列概述 #
Sequence(序列)是 Kotlin 中的一种惰性集合,只有在需要结果时才会执行操作。
1.1 与 List 的区别 #
kotlin
// List:立即执行
val list = listOf(1, 2, 3, 4, 5)
.map { println("map $it"); it * 2 }
.filter { println("filter $it"); it > 5 }
// 立即执行所有 map,再执行所有 filter
// Sequence:惰性执行
val sequence = sequenceOf(1, 2, 3, 4, 5)
.map { println("map $it"); it * 2 }
.filter { println("filter $it"); it > 5 }
// 不执行任何操作,直到需要结果
二、创建序列 #
2.1 sequenceOf #
kotlin
val sequence = sequenceOf(1, 2, 3, 4, 5)
2.2 asSequence #
kotlin
val list = listOf(1, 2, 3, 4, 5)
val sequence = list.asSequence()
2.3 generateSequence #
kotlin
// 无限序列
val infinite = generateSequence(1) { it + 1 }
// 有限序列
val finite = generateSequence(1) { if (it < 10) it + 1 else null }
// 带条件的无限序列
val odds = generateSequence(1) { it + 2 }.take(5)
// [1, 3, 5, 7, 9]
2.4 sequence 构建器 #
kotlin
val sequence = sequence {
yield(1)
yield(2)
yield(3)
yieldAll(listOf(4, 5))
}
// [1, 2, 3, 4, 5]
2.5 斐波那契序列 #
kotlin
val fibonacci = sequence {
var a = 0L
var b = 1L
while (true) {
yield(a)
val temp = a + b
a = b
b = temp
}
}
fibonacci.take(10).toList()
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
三、序列操作 #
3.1 中间操作 #
中间操作返回新的 Sequence,惰性执行:
kotlin
val sequence = sequenceOf(1, 2, 3, 4, 5)
.map { it * 2 } // 惰性
.filter { it > 4 } // 惰性
.take(3) // 惰性
// 此时没有执行任何操作
3.2 终端操作 #
终端操作触发实际计算:
kotlin
val sequence = sequenceOf(1, 2, 3, 4, 5)
.map { it * 2 }
.filter { it > 4 }
// 终端操作
sequence.toList() // [6, 8, 10]
sequence.toSet() // {6, 8, 10}
sequence.first() // 6
sequence.count() // 3
sequence.forEach { println(it) }
3.3 常用操作 #
kotlin
val sequence = sequenceOf(1, 2, 3, 4, 5)
// 映射
sequence.map { it * 2 }
sequence.flatMap { listOf(it, it * 2).asSequence() }
// 过滤
sequence.filter { it > 2 }
sequence.take(3)
sequence.drop(2)
sequence.distinct()
// 排序
sequence.sorted()
sequence.sortedBy { it }
// 聚合
sequence.reduce { acc, n -> acc + n }
sequence.fold(0) { acc, n -> acc + n }
sequence.sum()
sequence.count()
四、惰性求值示例 #
4.1 执行顺序对比 #
kotlin
// List:先完成所有 map,再完成所有 filter
val list = listOf(1, 2, 3, 4, 5)
.map { println("map: $it"); it * 2 }
.filter { println("filter: $it"); it > 5 }
.take(2)
// 输出:
// map: 1, map: 2, map: 3, map: 4, map: 5
// filter: 2, filter: 4, filter: 6, filter: 8, filter: 10
// Sequence:逐个元素处理
val result = listOf(1, 2, 3, 4, 5)
.asSequence()
.map { println("map: $it"); it * 2 }
.filter { println("filter: $it"); it > 5 }
.take(2)
.toList()
// 输出:
// map: 1, filter: 2
// map: 2, filter: 4
// map: 3, filter: 6
// map: 4, filter: 8
// 只处理到找到 2 个结果就停止
4.2 无限序列处理 #
kotlin
// 无限序列 + take
val result = generateSequence(1) { it + 1 }
.filter { it % 2 == 0 }
.map { it * it }
.take(5)
.toList()
// [4, 16, 36, 64, 100]
五、性能对比 #
5.1 大数据量处理 #
kotlin
// List:创建中间集合
val listResult = (1..1_000_000)
.map { it * 2 }
.filter { it > 1_000_000 }
.take(10)
.toList()
// 创建多个中间列表,内存消耗大
// Sequence:无中间集合
val sequenceResult = (1..1_000_000)
.asSequence()
.map { it * 2 }
.filter { it > 1_000_000 }
.take(10)
.toList()
// 不创建中间集合,内存效率高
5.2 何时使用 Sequence #
kotlin
// 适合使用 Sequence:
// 1. 数据量大
// 2. 多个中间操作
// 3. 不需要所有结果(如 take)
// 不适合使用 Sequence:
// 1. 数据量小
// 2. 只有一个操作
// 3. 需要多次遍历结果
六、序列构建器 #
6.1 yield #
kotlin
fun randomNumbers(seed: Int): Sequence<Int> = sequence {
var current = seed
while (true) {
yield(current)
current = (current * 1103515245 + 12345) and 0x7FFFFFFF
}
}
randomNumbers(42).take(5).toList()
6.2 yieldAll #
kotlin
fun <T> flatten(sequences: Sequence<Sequence<T>>): Sequence<T> = sequence {
sequences.forEach { seq ->
yieldAll(seq)
}
}
6.3 复杂序列 #
kotlin
fun treeSequence(root: Node): Sequence<Node> = sequence {
yield(root)
root.children.forEach { child ->
yieldAll(treeSequence(child))
}
}
七、实战示例 #
7.1 文件行处理 #
kotlin
fun processFile(filePath: String): Sequence<String> {
return File(filePath).useLines { lines ->
lines
.filter { it.isNotBlank() }
.map { it.trim() }
.filter { !it.startsWith("#") }
}
}
// 惰性处理,不会一次性加载整个文件
processFile("large_file.txt")
.take(100)
.forEach { println(it) }
7.2 分页数据 #
kotlin
fun <T> paginate(
fetch: (Int) -> List<T>,
pageSize: Int
): Sequence<T> = sequence {
var page = 0
while (true) {
val items = fetch(page)
if (items.isEmpty()) break
yieldAll(items)
page++
}
}
// 惰性加载分页数据
val allData = paginate({ page -> api.fetchPage(page) }, 20)
allData.take(50).toList() // 只加载前 50 条
7.3 素数序列 #
kotlin
fun primes(): Sequence<Int> = sequence {
val primes = mutableListOf<Int>()
var current = 2
while (true) {
var isPrime = true
for (p in primes) {
if (p * p > current) break
if (current % p == 0) {
isPrime = false
break
}
}
if (isPrime) {
primes.add(current)
yield(current)
}
current++
}
}
primes().take(10).toList()
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
八、序列 vs List 选择 #
| 场景 | 推荐 |
|---|---|
| 数据量大 | Sequence |
| 多个中间操作 | Sequence |
| 只需要部分结果 | Sequence |
| 数据量小 | List |
| 需要多次遍历 | List |
| 需要索引访问 | List |
九、最佳实践 #
9.1 使用 asSequence 转换 #
kotlin
// 推荐
val result = list.asSequence()
.map { ... }
.filter { ... }
.toList()
// 不推荐(小数据量)
val result = list
.map { ... }
.filter { ... }
9.2 注意终端操作 #
kotlin
// 错误:忘记终端操作
val sequence = list.asSequence().map { it * 2 }
// 不会执行任何操作
// 正确
val result = list.asSequence()
.map { it * 2 }
.toList() // 终端操作
十、总结 #
Sequence 要点:
| 特性 | 说明 |
|---|---|
| 惰性求值 | 延迟执行 |
| 无中间集合 | 内存效率高 |
| 无限序列 | 支持无限数据 |
| 终端操作 | 触发计算 |
下一步,让我们学习 协程基础!
最后更新:2026-03-27