gpt4 book ai didi

Kotlin 的 Iterable 和 Sequence 看起来完全一样。为什么需要两种类型?

转载 作者:IT老高 更新时间:2023-10-28 13:26:10 25 4
gpt4 key购买 nike

这两个接口(interface)都只定义了一个方法

public operator fun iterator(): Iterator<T>

文档说 Sequence 意味着惰性。但是 Iterable 不是也很懒惰吗(除非有 Collection 支持)?

最佳答案

主要区别在于 Iterable<T> 的 stdlib 扩展函数的语义和实现。和 Sequence<T> .

  • 对于Sequence<T> ,扩展函数尽可能延迟执行,类似于 Java Streams intermediate 操作。例如, Sequence<T>.map { ... } 返回另一个 Sequence<R>并且直到像 toList 这样的 终端 操作才真正处理这些项目或 fold被调用。

    考虑这段代码:

    val seq = sequenceOf(1, 2)
    val seqMapped: Sequence<Int> = seq.map { print("$it "); it * it } // intermediate
    print("before sum ")
    val sum = seqMapped.sum() // terminal

    打印出来:

    before sum 1 2

    Sequence<T>当您想尽可能减少在 终端 操作中完成的工作时,旨在用于惰性使用和高效流水线,与 Java Streams 相同。然而,惰性引入了一些开销,这对于较小集合的常见简单转换是不可取的,并且会降低它们的性能。

    一般来说,没有很好的方法来确定何时需要它,因此在 Kotlin 标准库中,惰性被显式化并提取到 Sequence<T>接口(interface)以避免在所有 Iterable 上使用它默认为 s。

  • 对于Iterable<T> ,相反,具有 intermediate 操作语义的扩展函数急切地工作,立即处理项目并返回另一个 Iterable .例如, Iterable<T>.map { ... } 返回 List<R>里面有映射结果。

    Iterable 的等效代码:

    val lst = listOf(1, 2)
    val lstMapped: List<Int> = lst.map { print("$it "); it * it }
    print("before sum ")
    val sum = lstMapped.sum()

    打印出来:

    1 2 before sum

    如上所述,Iterable<T>默认情况下是非懒惰的,这个解决方案很好地展示了自己:在大多数情况下它有很好的 locality of reference从而利用 CPU 缓存、预测、预取等,即使是集合的多次复制仍然可以很好地工作,并且在具有小集合的简单情况下表现更好。

    如果您需要对评估管道进行更多控制,可以使用 Iterable<T>.asSequence() 显式转换为惰性序列。功能。

关于Kotlin 的 Iterable 和 Sequence 看起来完全一样。为什么需要两种类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35629159/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com