0Pricing
Kotlin Academy · 课时

惰性操作

避免创建中间列表

惰性操作 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。

惰性操作

序列的强大之处在于惰性操作。中间操作会构建流水线,但不会立即运行;只有终止操作才会逐个拉取元素。这样可以避免创建中间列表。

无需中间列表

对于集合,每个 map 和 filter 都会分配一个新列表。对于序列,元素会流经所有步骤,而不会创建这些临时列表。

fun main() {
    val result = (1..6).asSequence()
        .map { it * it }
        .filter { it % 2 == 0 }
        .toList()
    println(result)
}

观察惰性行为

如果没有终止操作,任何匿名函数都不会运行。流水线在被消费之前只是一个处理方案。

fun main() {
    val pipeline = (1..3).asSequence()
        .map { println("map $it"); it }
    println("Built pipeline, nothing ran")
    pipeline.toList()
}

take 限制处理量

take(n) 是一种惰性中间操作。与无限生成器结合使用时,它会在生成 n 个元素后停止。

fun main() {
    val firstThree = generateSequence(1) { it + 1 }
        .map { it * 10 }
        .take(3)
        .toList()
    println(firstThree)
}

first 提前终止处理

像 first 这样的终止操作一旦获得所需结果就会停止,完全跳过其余元素。

fun main() {
    val result = (1..1000).asSequence()
        .map { println("processing $it"); it }
        .first { it > 3 }
    println("Found $result")
}

逐元素流式处理

在序列中,元素 1 先经过 map,再经过 filter;然后处理元素 2,依此类推。这种顺序支持提前终止处理,也避免缓存所有结果。

fun main() {
    listOf(1, 2, 3, 4).asSequence()
        .filter { println("filter $it"); it % 2 == 0 }
        .map { println("map $it"); it * 10 }
        .toList()
}

takeWhile 和 dropWhile

takeWhile 会持续生成元素,直到谓词失败;dropWhile 会在谓词成立时跳过开头的元素。这两者都是惰性的。

fun main() {
    val nums = generateSequence(1) { it + 1 }
    println(nums.takeWhile { it < 5 }.toList())
}

避免无效计算

由于在被消费之前不会执行任何操作,而且消费过程可以提前停止,因此开销较大的转换只会应用于实际到达终止操作的元素。

fun main() {
    val result = (1..100).asSequence()
        .map { it * 2 }
        .filter { it > 10 }
        .take(2)
        .toList()
    println(result)
}

重复使用序列

大多数序列可以迭代多次,每次都会重新运行流水线。但是,来自一次性数据源(例如迭代器)的序列只能消费一次。请留意数据源。

fun main() {
    val seq = sequenceOf(1, 2, 3).map { it * 2 }
    println(seq.toList())
    println(seq.sum())
}

有状态操作与无状态操作

大多数操作都是无状态的(一次处理一个元素)。有些操作(例如 sorted 或 distinct)是有状态的,必须缓存或扫描所有元素,因此会削弱惰性带来的优势。

fun main() {
    val result = sequenceOf(3, 1, 2, 1).distinct().sorted().toList()
    println(result)
}

惰性操作的收益

惰性操作通过跳过中间列表来节省内存,并通过提前终止处理来节省时间。数据越多,终止操作的筛选性越强,收益就越大。

快速检查

序列链中的匿名函数实际上会在什么时候执行?

回顾

惰性操作会构建一个流水线,只有终止操作消费它时才会运行,从而避免中间列表,并支持通过 first、take 和 takeWhile 提前终止处理。请注意 sorted 之类的有状态操作。接下来,您将判断什么时候序列优于集合。

常见问题解答

「惰性操作」课时是免费的吗?

是的 — 「惰性操作」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。

「惰性操作」这节课中我会学到什么?

避免创建中间列表 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Kotlin Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「惰性操作」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Kotlin Academy 课中编写并运行代码吗?

能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么使用序列
  2. 创建序列
  3. 惰性操作
  4. 序列与集合
← 返回 Kotlin Academy