What are views for collections and when would you want to use them?

In Scala, for many (all?) types of collections you can create views.

What exactly is a view and for which purposes are views useful?


Views are non-strict versions of collections. This means that the elements are calculated at access and not eagerly as in normal collections.

As an example take the following code:

val xs = List.tabulate(5)(_ + 1)
val ys = xs.view map { x => println(x); x * x }

Just this will not print anything but every access to the list will perform the calculation and print the value, i.e. every call to ys.head will result in 1 being printed. If you want to get a strict version of the collection again you can call force on it. In this case you will see all numbers printed out.

One use for views is when you need to traverse a collection of values which are expensive to compute and you only need one value at a time. Also views let you build lazy sequences by calling toStream on them that will also cache the evaluated elements.


One use case is when you need to collect first result of elements transformation:

    case class Transform(n: Int) { println("Transform "+n)}
    val list = List(1,2,3,4,5)
    list.view.map(v => Transform(v)).collectFirst{case Transform(3) => println("found")}

Prints:

Transform 1
Transform 2
Transform 3
found

While:

    list.map(v => Transform(v)).collectFirst{case Transform(3) => println("found")}

Prints:

Transform 1
Transform 2
Transform 3
Transform 4
Transform 5
found

See Views from Scala 2.8 Collections API.

Scala collections are by default strict in all their transformers, except for Stream, which implements all its transformer methods lazily. However, there is a systematic way to turn every collection into a lazy one and vice versa, which is based on collection views. A view is a special kind of collection that represents some base collection, but implements all transformers lazily.

...

There are two reasons why you might want to consider using views. The first is performance. You have seen that by switching a collection to a view the construction of intermediate results can be avoided. These savings can be quite important.

...

The second use case applies to views over mutable sequences. Many transformer functions on such views provide a window into the original sequence that can then be used to update selectively some elements of that sequence.