你想深入了解 Kotlin 中創(chuàng)建 Sequence(序列)的兩個(gè)核心函數(shù):sequenceOf 和 generateSequence,包括它們的區(qū)別、使用規(guī)則和實(shí)際案例,我會(huì)幫你理清這兩個(gè)函數(shù)的適用場(chǎng)景和使用方式,讓你能精準(zhǔn)選擇合適的函數(shù)創(chuàng)建序列。
一、核心概念先理清
首先明確:sequenceOf 和 generateSequence 都是 Kotlin 標(biāo)準(zhǔn)庫(kù)提供的創(chuàng)建 Sequence 的頂層函數(shù),但設(shè)計(jì)目標(biāo)完全不同:
-
sequenceOf:用于創(chuàng)建有限的、已知元素的序列(靜態(tài)序列); -
generateSequence:用于創(chuàng)建動(dòng)態(tài)生成的序列(可無(wú)限、可按需生成,核心是惰性)。
二、sequenceOf 詳解
1. 定義與規(guī)則
sequenceOf 是一個(gè)可變參數(shù)函數(shù),接收一組確定的元素,直接封裝成 Sequence。
- 語(yǔ)法:
fun <T> sequenceOf(vararg elements: T): Sequence<T> - 核心特點(diǎn):元素是預(yù)先確定的,序列長(zhǎng)度固定,本質(zhì)是 “把已知元素包裝成序列”。
2. 基礎(chǔ)案例
fun main() {
// 1. 基礎(chǔ)使用:創(chuàng)建有限序列
val numberSequence = sequenceOf(1, 2, 3, 4, 5)
// 執(zhí)行操作(惰性,直到終止操作觸發(fā))
val result = numberSequence
.filter { it % 2 == 0 }
.map { it * 10 }
.toList()
println(result) // 輸出:[20, 40]
// 2. 空序列:sequenceOf() 或 emptySequence()
val emptySeq1 = sequenceOf<Int>()
val emptySeq2 = emptySequence<Int>()
println(emptySeq1.count()) // 輸出:0
println(emptySeq2.count()) // 輸出:0
}
3. 與 listOf 的對(duì)比
sequenceOf(1,2,3) 等價(jià)于 listOf(1,2,3).asSequence(),但 sequenceOf 更直接(無(wú)需先創(chuàng)建 List 再轉(zhuǎn)換):
fun main() {
// 兩種方式等價(jià),但sequenceOf更簡(jiǎn)潔
val seq1 = sequenceOf(1, 2, 3)
val seq2 = listOf(1, 2, 3).asSequence()
println(seq1.toList() == seq2.toList()) // 輸出:true
}
三、generateSequence 詳解
generateSequence 是創(chuàng)建動(dòng)態(tài)序列的核心函數(shù),它通過(guò) “種子值 + 生成器函數(shù)” 按需生成元素,支持無(wú)限序列(惰性的核心體現(xiàn))。
1. 兩種重載形式
| 函數(shù)簽名 | 說(shuō)明 | 適用場(chǎng)景 |
|---|---|---|
fun <T : Any> generateSequence(nextFunction: () -> T?): Sequence<T> |
無(wú)初始種子,直接通過(guò)函數(shù)生成下一個(gè)元素 | 無(wú)初始值的動(dòng)態(tài)生成(如讀取文件行) |
fun <T> generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> |
有初始種子,基于前一個(gè)元素生成下一個(gè) | 有初始值的遞推生成(如自然數(shù)、斐波那契) |
核心規(guī)則:
- 生成器函數(shù)返回
null時(shí),序列終止; - 若生成器函數(shù)永遠(yuǎn)不返回
null,則生成無(wú)限序列; - 元素是按需生成的(直到終止操作觸發(fā),才生成需要的元素)。
2. 案例 1:有種子的有限序列
fun main() {
// 生成從1開(kāi)始,每次+2,直到>10為止的序列
val oddNumbers = generateSequence(1) { prev ->
val next = prev + 2
if (next > 10) null else next // 返回null終止序列
}
// 轉(zhuǎn)換為L(zhǎng)ist,觸發(fā)元素生成
println(oddNumbers.toList()) // 輸出:[1, 3, 5, 7, 9]
}
3. 案例 2:無(wú)限序列(核心場(chǎng)景)
generateSequence 最強(qiáng)大的地方是支持無(wú)限序列(因?yàn)槎栊?,不?huì)一次性生成所有元素):
fun main() {
// 生成無(wú)限自然數(shù)序列(1,2,3,...)
val naturalNumbers = generateSequence(1) { it + 1 }
// 只取前5個(gè)元素,不會(huì)生成全部無(wú)限元素
val first5 = naturalNumbers.take(5).toList()
println(first5) // 輸出:[1, 2, 3, 4, 5]
// 找第一個(gè)大于100的偶數(shù)(僅生成到102就終止)
val firstEvenOver100 = naturalNumbers
.filter { it % 2 == 0 }
.first { it > 100 }
println(firstEvenOver100) // 輸出:102
}
4. 案例 3:無(wú)種子的序列(讀取動(dòng)態(tài)數(shù)據(jù))
模擬 “逐行讀取文件”(實(shí)際場(chǎng)景中,文件行是動(dòng)態(tài)的、未知長(zhǎng)度的):
fun main() {
// 模擬文件行生成器(實(shí)際可替換為File.reader().readLine())
var lineNumber = 0
val fileLines = generateSequence {
lineNumber++
if (lineNumber > 3) null else "第${lineNumber}行內(nèi)容"
}
// 遍歷輸出(按需生成每一行)
fileLines.forEach { println(it) }
// 輸出:
// 第1行內(nèi)容
// 第2行內(nèi)容
// 第3行內(nèi)容
}
5. 案例 4:生成斐波那契數(shù)列
fun main() {
// 種子是Pair(前一個(gè)數(shù), 當(dāng)前數(shù)),初始為(0,1)
val fibonacci = generateSequence(Pair(0, 1)) { (a, b) ->
Pair(b, a + b) // 下一個(gè)數(shù)=前兩個(gè)數(shù)之和
}.map { it.second } // 提取數(shù)列值
// 取前10個(gè)斐波那契數(shù)
val first10Fib = fibonacci.take(10).toList()
println(first10Fib) // 輸出:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
}
四、sequenceOf vs generateSequence 核心對(duì)比
| 特性 | sequenceOf | generateSequence |
|---|---|---|
| 元素來(lái)源 | 預(yù)先確定的靜態(tài)元素 | 生成(種子 + 生成器函數(shù)) |
| 序列長(zhǎng)度 | 固定、有限 | 可有限(返回 null 終止)、可無(wú)限 |
| 惰性程度 | 低(元素已確定,僅操作惰性) | 高(元素按需生成,操作也惰性) |
| 適用場(chǎng)景 | 已知元素的序列(如固定列表轉(zhuǎn)序列) | 動(dòng)態(tài)生成的序列(如自然數(shù)、斐波那契、讀取動(dòng)態(tài)數(shù)據(jù)) |
五、避坑點(diǎn)
-
無(wú)限序列必須加終止操作:
若用generateSequence創(chuàng)建無(wú)限序列,必須搭配take()、first()等短路操作,否則調(diào)用toList()會(huì)導(dǎo)致無(wú)限循環(huán) / 內(nèi)存溢出:
// 錯(cuò)誤示例(無(wú)限循環(huán)):
// val allNatural = generateSequence(1) { it + 1 }.toList()
// 正確示例(加take限制):
val limited = generateSequence(1) { it + 1 }.take(100).toList()
-
generateSequence 的種子可為 null:
若種子為null且生成器函數(shù)也返回null,則序列為空:
val emptySeq = generateSequence(null) { it ?: null }
println(emptySeq.count()) // 輸出:0
總結(jié)
-
sequenceOf:用于創(chuàng)建已知元素的有限序列,是 “靜態(tài)元素的序列包裝器”,語(yǔ)法簡(jiǎn)潔,等價(jià)于
listOf(...).asSequence()。 - generateSequence:用于創(chuàng)建動(dòng)態(tài)生成的序列,支持無(wú)限序列和按需生成,核心是 “種子 + 生成器函數(shù)”,是處理動(dòng)態(tài) / 無(wú)限數(shù)據(jù)的首選。
- 選擇原則:元素已知用
sequenceOf,元素需要?jiǎng)討B(tài)生成(如遞推、讀取動(dòng)態(tài)數(shù)據(jù))用generateSequence。