This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 10.12, “Using Iterators with Scala Collection Classes”
You want (or need) to work with an iterator in a Scala application.
Although using an iterator with
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
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
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
- An introduction to Scala iterators
- The Iterator trait