How to loop over a Scala collection with foreach

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 10.9, “How to loop over a Collection with foreach”.

Problem

You want to iterate over the elements in a  Scala collection class with the foreach method.

Solution

The foreach method on Scala collections classes takes a function as an argument. The function you define should take an element as an input parameter, and should not return anything. The input parameter type should match the type stored in the collection. As foreach executes, it passes one element at a time from the collection to your function until it reaches the last element in the collection.

Side Effects: The foreach method applies your function to each element of the collection, but it doesn’t return a value. Because it doesn’t return anything, it’s said that it’s used for its “side effect.”

As an example, a common use of foreach is to output information:

scala> val x = Vector(1, 2, 3)
x: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> x.foreach((i: Int) => println(i))
1
2
3

That’s the longhand way of writing that code. For most expressions, Scala can infer the type, so specifying i: Int isn’t necessary:

args.foreach(i => println(i))

You can further shorten this expression by using the ubiquitous underscore wildcard character instead of using a temporary variable:

args.foreach(println(_))

In a situation like this, where a function literal consists of one statement that takes a single argument, it can be condensed to this form:

args.foreach(println)

For a simple case like this, the syntax in the last example is typically used.

Discussion

As long as your function (or method) takes one parameter of the same type as the elements in the collection and returns nothing (Unit), it can be called from a foreach method. In the following example, the printIt method takes a Char, does something with it, and returns nothing:

def printIt(c: Char) { println(c) }

Because a String is a sequence of type Char, printIt can be called in a foreach method on a String as follows:

"HAL".foreach(c => printIt(c))
"HAL".foreach(printIt)

If your algorithm is used only once, you don’t have to declare it as a method or function; just pass it to foreach as a function literal:

"HAL".foreach((c: Char) => println(c))

To declare a multiline function, use this format:

val longWords = new StringBuilder
"Hello world it's Al".split(" ").foreach{ e =>
    if (e.length > 4) longWords.append(s" $e")
    else println("Not added: " + e)
}

To understand this example, it may be helpful to know the split method used in that function creates an Array[String], as shown here:

scala> "Hello world it's Al".split(" ")
res0: Array[java.lang.String] = Array(Hello, world, it's, Al)

In addition to using the foreach method on sequential collections, it’s also available on the Map class. The Map implementation of foreach passes two parameters to your function. You can handle those parameters as a tuple:

val m = Map("fname" -> "Tyler", "lname" -> "LeDude")
m foreach (x => println(s"${x._1} -> ${x._2}"))

However, I generally prefer the following approach:

movieRatings.foreach {
    case(movie, rating) => println(s"key: $movie, value: $rating")
}

See Also