【发布时间】:2023-03-18 06:20:02
【问题描述】:
在尝试了解流、迭代器和集合视图之间的区别时,我偶然发现了以下奇怪的行为。
这里是代码(map 和 filter 只是打印它们的输入并原封不动地转发):
object ArrayViewTest {
def main(args: Array[String]) {
val array = Array.range(1,10)
print("stream-map-head: ")
array.toStream.map(x => {print(x); x}).head
print("\nstream-filter-head: ")
array.toStream.filter(x => {print(x); true}).head
print("\niterator-map-head: ")
array.iterator.map(x => {print(x); x}).take(1).toArray
print("\niterator-filter-head: ")
array.iterator.filter(x => {print(x); true}).take(1).toArray
print("\nview-map-head: ")
array.view.map(x => {print(x); x}).head
print("\nview-filter-head: ")
array.view.filter(x => {print(x); true}).head
}
}
及其输出:
stream-map-head: 1
stream-filter-head: 1
iterator-map-head: 1
iterator-filter-head: 1
view-map-head: 1
view-filter-head: 123456789 // <------ WHY ?
为什么在视图上调用过滤器会处理整个数组? 我希望通过调用 head 只驱动一次过滤器的评估,就像在所有其他情况下一样,特别是在使用 map on view 时。
我缺少哪些见解?
(评论的小问题,为什么迭代器上没有头?)
编辑:
scala.collection.mutable.ArraySeq.range(1,10)、scala.collection.mutable.ArrayBuffer.range(1,10) 和 scala.collection.mutable.StringBuilder.newBuilder.append("123456789") 实现了相同的奇怪行为(如这里的 scala.Array.range(1,10))。
但是,对于所有其他可变集合和所有不可变集合,视图上的过滤器按预期工作并输出1。
【问题讨论】:
-
(mini-side-answer) 如果您想获得迭代器的第一个元素,则必须使用
next推进它并调用它,例如两次会有问题。