序列概述与使用环境

除了集合之外,Kotlin 标准库还包含另一种容器类型——序列Sequence<T>)。 序列提供与 Iterable 相同的函数,但实现另一种方法来进行多步骤集合处理。

当 Iterable 的处理包含多个步骤时,它们会优先执行:每个处理步骤完成并返回其结果——中间集合。

在此集合上执行以下步骤。反过来,序列的多步处理在可能的情况下会延迟执行:仅当请求整个处理链的结果时才进行实际计算。

操作执行的顺序也不同:Sequence 对每个元素逐个执行所有处理步骤。 反过来,Iterable 完成整个集合的每个步骤,然后进行下一步。

因此,这些序列可避免生成中间步骤的结果,从而提高了整个集合处理链的性能。 但是,序列的延迟性质增加了一些开销,这些开销在处理较小的集合或进行更简单的计算时可能很重要。 因此,应该同时考虑使用 Sequence 与 Iterable,并确定在哪种情况更适合。

创建序列

初始化元素的方式创建序列

要创建一个序列,调用 sequenceOf() 函数,列出元素作为其参数。

val numbersSequence = sequenceOf("four", "three", "two", "one")

由 Iterable创建

如果已经有一个 Iterable 对象(例如 List 或 Set),则可以通过调用 asSequence() 从而创建一个序列。

val numbers = listOf("one", "two", "three", "four")
val numbersSequence = numbers.asSequence()

函数创建

创建序列的另一种方法是通过使用计算其元素的函数来构建序列。 要基于函数构建序列,请以该函数作为参数调用 generateSequence()。 (可选)可以将第一个元素指定为显式值或函数调用的结果。 当提供的函数返回 null 时,序列生成停止。因此,以下示例中的序列是无限的。

val oddNumbers = generateSequence(1) { it + 2 } // `it` 是上一个元素
println(oddNumbers.take(5).toList()) // [1, 3, 5, 7, 9]
//println(oddNumbers.count())     // 错误:此序列是无限的。

要使用 generateSequence() 创建有限序列,请提供一个函数,该函数在需要的最后一个元素之后返回 null

val oddNumbersLessThan10 = generateSequence(1) {
    if (it + 2 < 10) it + 2
    else null
}
println(oddNumbersLessThan10.count()) //5
print

组块创建

有一个函数可以逐个或按任意大小的组块生成序列元素——sequence() 函数。 此函数采用一个 lambda 表达式,其中包含 yield() 与 yieldAll() 函数的调用。 它们将一个元素返回给序列使用者,并暂停 sequence() 的执行,直到使用者请求下一个元素。 yield() 使用单个元素作为参数;yieldAll() 中可以采用 Iterable 对象、Iterable 或其他 SequenceyieldAll() 的 Sequence 参数可以是无限的。 当然,这样的调用必须是最后一个:之后的所有调用都永远不会执行。

val oddNumbers = sequence {
    yield(1)
    yieldAll(listOf(3, 5))
    yieldAll(generateSequence(7) { it + 2 })
}
println(oddNumbers.take(5).toList())  // [1, 3, 5, 7, 9]

序列的操作

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐