How to use iterators with Scala collections classes

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 10.12, “Using Iterators with Scala Collection Classes”

Problem

You want (or need) to work with an iterator in a Scala application.

Solution

Although using an iterator with hasNext() and next() is a common way to loop over a collection in Java, they aren’t commonly used in Scala, because Scala collections have methods like map and foreach that let you implement algorithms more concisely. To be clear, in Scala I’ve never written code like this:

// don't do this
val it = collection.iterator
while (it.hasNext) ...

That being said, sometimes you’ll run into an iterator, with one of the best examples being the io.Source.fromFile method. This method returns an iterator, which makes sense, because when you’re working with very large files, it’s not practical to read the entire file into memory.

An important part of using an iterator is knowing that it’s exhausted after you use it. As you access each element, you mutate the iterator, and the previous element is discarded.

For instance, if you use foreach to iterate over an iterator’s elements, the call works the first time:

scala> val it = Iterator(1,2,3)
it: Iterator[Int] = non-empty iterator

scala> it.foreach(println)
1
2
3

But when you attempt the same call a second time, you won’t get any output, because the iterator has been exhausted:

scala> it.foreach(println)
(no output here)

An iterator isn’t a collection; instead, it gives you a way to access the elements in a collection, one by one. But an iterator does define many of the methods you’ll see in a normal collection class, including foreach, map, flatMap, collect, etc. You can also convert an iterator to a collection when needed:

val it = Iterator(1,2,3)
it.toArray

The REPL output shows the collections you can create from an iterator:

scala> it.to[Tab]
toArray         toBuffer        toIndexedSeq    toIterable      toIterator
toList          toMap           toSeq           toSet           toStream
toString        toTraversable

See Also

  • An introduction to Scala iterators
  • The Iterator trait