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个项目并完成。
如果您查看关于Sequence
和Iterable
之间差异的问答,可能会变得更加清楚:( 链接)
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()
前者会试图实例化无数的项目,而且可以预见的是,它会失败。