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

这两个接口都只定义了一种方法

public operator fun iterator(): Iterator 

文件说Sequence是懒惰的。 但是也不是可以Iterable懒惰(除非有一个Collection支持)?

    2 Solutions collect form web for “Kotlin的Iterable和Sequence看起来完全一样。 为什么需要两种types?”

    关键的区别在于IterableSequence的stdlib扩展函数的语义和实现。

    • 对于Sequence ,扩展函数在可能的情况下执行延迟,类似于Java Streams 中间操作。 例如, Sequence.map { ... }返回另一个Sequence ,实际上并不处理这些项目,直到调用像toListfold这样的终端操作。

      考虑这个代码:

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

      它打印:

       before sum 1 2 

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

      一般来说,没有什么好的方法来确定什么时候需要它,所以在Kotlin stdlib中,懒惰是明确的,并且提取到Sequence接口,以避免在所有的Iterable默认使用它。

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

      Iterable的等效代码:

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

      这打印出来:

       1 2 before sum 

      如上所述,默认情况下, Iterable是非惰性的,这个解决方案很好地展示了它:在大多数情况下,它具有良好的参考局部性,从而利用CPU缓存,预测,预取等优势,收集仍然工作得很好,并在小集合的简单情况下表现更好。

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

    完成热键的回答:

    注意Sequence和Iterable迭代如何思考你的元素是很重要的:

    序列示例:

      list.asSequence() .filter { field -> Log.d("Filter", "filter") field.value > 0 }.map { Log.d("Map", "Map") }.forEach { Log.d("Each", "Each") } 

    记录结果:

    filter – 地图 – 每个; filter – 映射 – 每个

    可重用的例子:

      list.filter { field -> Log.d("Filter", "filter") field.value > 0 }.map { Log.d("Map", "Map") }.forEach { Log.d("Each", "Each") } 

    filter – filter – 地图 – 地图 – 每个 – 每个

    Kotlin language will be the best programming language for Android.