【问题标题】:difference between toList().take(10) and take(10).toList() in kotlinkotlin 中 toList().take(10) 和 take(10).toList() 的区别
【发布时间】:2018-07-17 18:08:50
【问题描述】:

我只是在尝试新的kotlin 语言。我遇到了生成无限列表的序列。我生成了一个序列并尝试打印前 10 个元素。但是下面的代码没有打印任何东西:

fun main(args: Array<String>) {
    val generatePrimeFrom2 = generateSequence(3){ it + 2 }
    print(generatePrimeFrom2.toList().take(10))
}

但是当我在print 语句中更改take(10).toList() 时,它工作正常。为什么会这样?

这段代码对我来说很好用:

fun main(args: Array<String>) {
    val generatePrimeFrom2 = generateSequence(3){ it + 2 }
    print(generatePrimeFrom2.take(10).toList())
}

【问题讨论】:

  • “但是下面的代码没有打印任何东西:” - 它挂起并且没有打印任何东西吗?还是默默结束?
  • 它没有挂起,但它一直在执行@SergioTulentsev
  • 如果程序不产生任何输出,你如何分辨?
  • 第一个 sn-p 代码没有打印任何内容。但是第二个代码打印了输出。在下面的答案中得到了我的解决方案@SergioTulentsev 感谢您的宝贵时间

标签: kotlin


【解决方案1】:

generateSequence 函数生成一个序列,该序列要么是无限的,要么在传递给它的 lambda 返回 null 时结束。在你的情况下,它是{ it + 2 },它永远不会返回null,所以序列是无限的。

当您在序列上调用.toList() 时,它会尝试收集所有序列元素,因此如果序列是无限的,它将永远不会停止(除非索引溢出或发生内存不足错误),所以它确实不打印任何东西,因为它没有完成。

相反,在第二种情况下,您使用.take(10) 尝试收集其项目之前限制了序列中的元素数量。然后.toList() 调用简单地收集 10 个项目并完成。

如果您查看这个关于Sequence&lt;T&gt;Iterable&lt;T&gt; 之间差异的问答,可能会更清楚:(link)

【讨论】:

  • 是的,你是对的。我认为 IDE 应该在我对序列执行此操作时提示我 toList().take(10) will be infinite
【解决方案2】:

这是提示 -> generate infinite list。在第一个解决方案中,您首先要创建一个列表(等待无穷大),然后获取前 10 个元素。

在第二个 sn-p 中,从无限列表中只取前 10 个元素并将其更改为列表

【讨论】:

    【解决方案3】:

    generatePrimeFrom2.toList() 尝试计算/创建一个 infinite-length 列表。
    generatePrimeFrom2.toList().take(10) 然后从 infinite-length 列表中获取前 10 个元素。
    它不打印,因为它正在计算 infinite-length 列表。

    generatePrimeFrom2.take(10) 只尝试计算前 10 个元素。 generatePrimeFrom2.take(10).toList() 将前 10 个元素转换为列表。

    你知道,generateSequence(3){ it + 2 } 没有结尾。所以它有无限长。
    Sequences 没有实际值,需要时计算,但Lists 必须有实际值。

    【讨论】:

    • 是的,你是对的。我认为 IDE 应该在我对序列执行此操作时提示我 toList().take(10) will be infinite
    【解决方案4】:

    我遇到了生成无限列表的序列。

    这实际上是不正确的。要点是序列不是列表。它是一个惰性求值的构造,只有您请求的项目才会真正“物化”,即它们在堆上分配的内存。

    这就是为什么它不能互换的原因

    infiniteSeq.toList().take(10)
    

    infiniteSeq.take(10).toList()
    

    前者会尝试实例化无限多的项目,并且可以预见地会失败。

    【讨论】:

    • 是的,你是对的。我认为 IDE 应该在我对序列执行此操作时提示我 toList().take(10) will be infinite
    • IDEA 2018 可能会为此引入一些检查(不是 100% 确定)。
    猜你喜欢
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 2019-07-05
    • 1970-01-01
    相关资源
    最近更新 更多