在 Kotlin 中实现惰性列表
如果一个元素或表达式的值在定义时没有被计算,而是在它第一次被访问时被计算,则称它为惰性计算。在很多情况下它都能派上用场。例如,你可能有一个列表 A,你想从它创建一个过滤列表,我们称之为列表 B。如果你做如下的事情,过滤操作将在 B 的声明期间执行。
val A = listOf(1,2,3,4)
var B= A.filter { it%2==0 }
这迫使程序在定义 B 后立即对其进行初始化。虽然这对于一个小列表来说可能没什么大不了的,但它可能会导致较大对象的延迟。此外,我们可以延迟对象创建,直到我们第一次需要它。在这个秘籍中,我们将学习如何实现惰性列表。
例子
要创建惰性列表,我们需要将列表转换为序列。一个序列代表惰性求值的集合。让我们通过一个例子来理解它:
1. 在给定的示例中,我们首先根据元素的奇数或偶数过滤列表:
Kotlin
fun main(args: Array) {
val A= listOf(1,2,3,4)
var B=A.filter {
println ("Testing ${it}")
it%2==0
}
}
Kotlin
fun main(args: Array) {
val A = listOf(1,2,3,4).asSequence()
var B = A.filter{
println("testing ${it}")
it%2==0
}
}
Kotlin
fun main(args: Array) {
val A = listOf(1,2,3,4).asSequence()
var B = A.filter{
println("testing ${it}")
it%2==0
}
B.forEach{
println("printing ${it}")
}
}
输出:
Testing 1
Testing 2
Testing 3
Testing 4
在前面的示例中,仅在定义对象时才评估过滤器函数
2. 现在,让我们将列表转换为序列。将列表转换为序列仅一步之遥;您可以将任何列表转换为序列
使用.asSequence()方法,或通过Sequence { createIterator() }:
科特林
fun main(args: Array) {
val A = listOf(1,2,3,4).asSequence()
var B = A.filter{
println("testing ${it}")
it%2==0
}
}
3. 如果你运行前面的代码,你不会在控制台看到任何输出,因为对象还没有被创建。它将在首次访问列表 B 时创建:
科特林
fun main(args: Array) {
val A = listOf(1,2,3,4).asSequence()
var B = A.filter{
println("testing ${it}")
it%2==0
}
B.forEach{
println("printing ${it}")
}
}
输出:
testing 1
testing 2
printing 2
testing 3
testing 4
printing 4
访问项目时评估过滤器函数。这称为惰性求值。
Kotlin 中的序列可能是无界的,并且在事先不知道列表长度时使用。由于它可以是无限的,因此这种类型的结构需要惰性求值。考虑这个例子:
val seq = generateSequence(1) { it* 2 }
seq.take(10).forEach { print (” ${it} “) }
在这里, generateSequence生成一个无限数的序列,但是当我们调用take(10)时,只有 10 个项目被评估和打印。