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)
Other than using next,hasNext, wh开发者_开发知识库en should I choose iterator over view or view over iterator?
There's a huge difference between iterators and views. Iterators are use once only, compute on demand, while views are use multiple times, recompute each time, but only the elements needed. For instance:
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)
view
produces a lazy collection/stream. It's main charm is that it won't try and build the whole collection. This could prevent a OutOfMemoryError or improve performance when you only need the first few items in the collection. iterator
makes no such guarantee.
One more thing. At least on Range
, view
returns a SeqView
, which is a sub-type of Seq
, so you can go back or start again from the beginning and do all that fun sequency stuff.
I guess the difference between an iterator and a view is a matter of in-front and behind. Iterators are expected to release what has been seen. Once next
has been called, the previous is, hopefully, let go. Views are the converse. They promise to not acquire what has not been requested. If you have a view of all prime numbers, an infinite set, it has only acquired those primes you've asked for. It you wanted the 100th, 101 shouldn't be taking up memory yet.
This page talks about when to use views.
In summary, views are a powerful tool to reconcile concerns of efficiency with concerns of modularity. But in order not to be entangled in aspects of delayed evaluation, you should restrict views to two scenarios. Either you apply views in purely functional code where collection transformations do not have side effects. Or you apply them over mutable collections where all modifications are done explicitly. What's best avoided is a mixture of views and operations that create new collections while also having side effects.
精彩评论