迭代器和视图的方法有什么区别?

时间:2011-01-25 19:40:03

标签: scala collections

scala> (1 to 10).iterator.map{_ * 2}.toList
res1: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

scala> (1 to 10).view.map{_ * 2}.force
res2: Seq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

除了使用next,hasNext之外,何时应该在视图上选择迭代器还是在迭代器上查看?

3 个答案:

答案 0 :(得分:37)

迭代器和视图之间存在巨大差异。迭代器只使用一次,按需计算,而视图使用多次,每次重新计算,但只需要重新计算。例如:

scala> val list = List(1,2,3).map{x => println(x); x * 2}
1
2
3
list: List[Int] = List(2, 4, 6)

scala> list(2)
res14: Int = 6

scala> list(2)
res15: Int = 6

scala> val view = List(1,2,3).view.map{x => println(x); x * 2}
view: scala.collection.SeqView[Int,Seq[_]] = SeqViewM(...)

scala> view(2)
3
res12: Int = 6

scala> view(2)
3
res13: Int = 6

scala> val iterator = List(1,2,3).iterator.map{x => println(x); x * 2}
iterator: Iterator[Int] = non-empty iterator

scala> iterator.drop(2).next
1
2
3
res16: Int = 6

scala> iterator.drop(2).next
[Iterator.next] (Iterator.scala:29)
(access lastException for the full trace)

答案 1 :(得分:21)

view生成一个惰性集合/流。它的主要魅力在于它不会尝试构建整个系列。当您只需要集合中的前几个项目时,这可以防止OutOfMemoryError或提高性能。 iterator没有这样的保证。

还有一件事。至少在Range上,view会返回SeqView,这是Seq的子类型,因此您可以从头开始或重新开始,然后执行所有操作有趣的顺序的东西。

我认为迭代器和视图之间的区别是前后问题。预计迭代器将发布已经看到的内容。一旦调用了next,就可以放弃上一个。观点是相反的。他们承诺不会获得未被要求的东西。如果你有一个所有素数的视图,一个无限集,它只获得了你所要求的素数。你想要100,101不应该占用记忆。

答案 2 :(得分:0)

page讨论了何时使用视图。

  

总之,视图是调和问题的有力工具   关注模块化的效率。但为了不成为   在延迟评估的方面纠结,你应该限制观点   两种情况。您可以在纯功能代码中应用视图   集合转换没有副作用。或者您   将它们应用于所有修改完成的可变集合   明确。最好避免的是视图和操作的混合   创造新的集合,同时也有副作用。