toList()。take(10)和take(10).toList()in kotlin之间的区别

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

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

但是当我改变了print take(10).toList()print语句中工作正常。 为什么这样?

这段代码适合我:

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

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

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

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

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

在第二种情况下,相反,您可以在收集项目之前.take(10)限制序列中的元素数目。 然后, .toList()调用只收集10个项目并完成。

如果您查看关于SequenceIterable之间差异的问答,可能会变得更加清楚:( 链接)

generatePrimeFrom2.toList()试图计算/创建一个无限长度的列表。
generatePrimeFrom2.toList().take(10)然后从无限长度列表中取前10个元素。
它不打印,因为它正在计算无限长度的列表。

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

你知道, generateSequence(3){ it + 2 }没有结束 。 所以它有无限的长度。
Sequence s没有实际值,需要时计算,但List s必须有实际值。

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

这实际上并不正确。 重点是序列不是一个列表 。 这是一个懒惰的评估构造,只有你所要求的项目才会真正变成“物化”,也就是他们的内存分配在堆上。

这就是为什么它不能互相编写

 infiniteSeq.toList().take(10) 

 infiniteSeq.take(10).toList() 

前者会试图实例化无数的项目,而且可以预见的是,它会失败。