如果编写以下代码:
fun main(args: Array<String>) {
val letters = listOf("a", "b", "c", "d")
letters.map { print(it); it }.forEach { print(it) }
}
我得到以下输出:abcdabcd
但是,如果我改为将其更改为序列:
fun main(args: Array<String>) {
val letters = listOf("a", "b", "c", "d")
letters.asSequence().map { print(it); it }.forEach { print(it) }
}
我得到以下信息:aabbccdd
似乎Kotlin的序列不能保证“组操作”(例如map
或forEach
)将在另一个开始之前完成,但是当我们将这些操作应用于集合时,可以保证该操作将一次完成。
我们如何保证在开始执行下一个链接的“组操作”之前,将对集合或序列中的所有元素应用诸如map
或forEach
之类的“组操作” ?
答案 0 :(得分:3)
我们如何保证在开始执行下一个链接的“组操作”之前,将诸如map或forEach之类的“组操作”应用于集合或序列中的所有元素?
行为取决于输入是Collection
还是Sequence
。
"abcd"
,然后再次看到"abcd"
的原因。"aa"
,然后看到"bb"
等的原因。主要要了解的是Kotlin序列是 lazy 。每当您转换Sequence
(例如通过map
或其他函数)时,该转换也是 缓慢应用的。只有在您实际评估序列中的元素(在您的情况下,这是由forEach
完成)时,转换才适用。
如果您需要Collection
中的Sequence
行为,则必须先将序列转换为集合。您可以调用sequence.toList()
或对其进行转换,但是无法从Sequence
中获得“渴望的”行为。
我们来看看两种不同的情况。
letters
是List<String>
列表不是很懒。为了将一个map
List
转换为另一个map { print(it); it }
,我们必须遍历整个输入列表,转换每个元素并构建输出列表。考虑到这一点...
第一个操作"a", "b", "c", "d"
从输入中读取每个值,然后打印并创建一个新列表。它返回一个包含"abcd"
的列表,并且程序已打印forEach { print(it) }
。
第二个操作"abcd"
遍历列表并打印每个元素。完成此操作后,程序将再次打印"abcdabcd"
,总输出为letters
。
Sequence<String>
是map
序列是惰性的。为了使Sequence
一个TransformingSequence
到另一个print(it); return it
,该程序保留了转换方法,并等待直到别人实际上需要一个值,然后才能执行转换。所以...
第一个操作将创建一个新的TransformingSequence
,它同时保留原始序列和print
转换器。它返回这个新序列,程序尚未打印任何内容。
第二个操作是“终端”(即它实际上是评估序列中的每个元素)。遍历序列并打印每个元素。但是请记住:我们要遍历的序列是一个forEach
,它本身会打印每个元素!因此,"aa"
调用中的第一个"bb"
动作将打印"aabbccdd"
,第二个动作将打印{{1}},依此类推,总输出为{{1}}。>