The following answer is taken from the Views section in the Hands-on Scala book.
When you chain multiple transformations on a collection, we are creating many intermediate collections
that are immediately thrown away. For example, in the following code:
@ val myArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
@ val myNewArray = myArray.map(x => x + 1).filter(x => x % 2 == 0).slice(1, 3)
myNewArray: Array[Int] = Array(4, 6)
The chain of .map
.filter
.slice
operations ends up traversing the collection three times, creating three
new collections, but only the last collection ends up being stored in myNewArray
and the others are
discarded.
myArray
1,2,3,4,5,6,7,8,9
map(x => x + 1)
2,3,4,5,6,7,8,9,10
filter(x => x % 2 == 0)
2,4,6,8,10
slice(1, 3)
myNewArray
4,6
This creation and traversal of intermediate collections is wasteful. In cases where you have long chains of
collection transformations that are becoming a performance bottleneck, you can use the .view
method
together with .to
to fuse the operations together:
@ val myNewArray = myArray.view.map(_ + 1).filter(_ % 2 == 0).slice(1, 3).to(Array)
myNewArray: Array[Int] = Array(4, 6)
Using .view
before the map/filter/slice
transformation operations defers the actual traversal and
creation of a new collection until later, when we call .to
to convert it back into a concrete collection type:
myArray
1,2,3,4,5,6,7,8,9
view map filter slice to
myNewArray
4,6
This allows us to perform this chain of map/filter/slice
transformations with only a single traversal, and
only creating a single output collection. This reduces the amount of unnecessary processing and memory
allocations.