1. Overview

In Scala, Map is a data structure used to map from keys to values. The Scala Standard Library has implemented the Map structure on both immutable and mutable collections for multiple use cases. Immutable maps are the default and are more commonly used.

In this tutorial, we’ll look at how Maps work to understand how to iterate over them.

2. Map Structure

Let’s start with a simple Map to visualize the data. Imagine a scenario where we need to get the ASCII (American Standard Code for Information Interchange) value from chars.

We could implement a Map with Chars as the keys, and the value from each key will be its corresponding numeric ASCII value:

val asciiConversion = Map(
  'a' -> 97,
  'b' -> 98,
  'c' -> 99,
  'd' -> 100
)

In this Map implementation example, we see that we first set the key, then we use the -> operator to indicate the value from the key.

To access the value from a key, we can use the get() function:

asciiConversion.get('a')

This function’s output will be Some(97). Note that this returns us a sub-type of Option, which means the result can vary given the input, depending on the settled keys in the Map. It will return Some(value) when the key exists in the Map, and None when it doesn’t exist. Option and None are briefly explained in The Option Type in Scala.

To clarify, we’ve seen that there will be two data types when working with a Map – the key and the value.

3. Higher-Order Functions Iteration

So far, we understand that a Map works with two data types.

Now, let’s suppose we want to iterate over all pairs of values using higher-order functions as foreach, map, and reduce.

For instance, this method will receive each pair as a Tuple2. Therefore, we can treat it in two different ways.

3.1. Raw Tuples

When iterating, we can treat the value in the function as when working with tuples.

Let’s take a look:

asciiConversion.foreach(pair => print(s"Key: ${pair._1}, Value: ${pair._2}"))

Here, we’re using the definitions _1 and _2 to access the key and value, respectively.

3.2. Case Pattern

On the other hand, when handling tuples in Scala, we also can split the values. Let’s see an example:

asciiConversion.foreach { case (key, value) => print(s"Key: $key, Value: $value") }

Case, the pattern matching mechanism, can be used to set the layout of the data, separating the key and value in two different variables.

4. For Iteration

Similarly, as seen before, for loops will deal with keys and values from the Map as in the higher-order function approach, with the Tuple2 class*.* As a result, we can split values or not. Let’s see both ways in an example:

for (pair <- asciiConversion)
  println(s"${pair._1} : ${pair._2}")

for ((key, value) <- asciiConversion)
  println(s"$key : $value")

In both cases, the output will be:

a : 97
b : 98
c : 99
d : 100

5. All Keys or Values Iteration

Besides both methods that we’ve already seen to iterate over Maps in Scala, there’s a third: We can handle keys or values of a Map unitarily.

For instance, we can use the definitions keys and values to reference all keys or values from a Map.

To reference all the keys, we can write:

asciiConversion.keys
// Iterable(a, b, c, d): scala.collection.Iterable[scala.Char]

And for all values, we’d write:

asciiConversion.values
// Iterable(97, 98, 99, 100): scala.collection.Iterable[scala.Int]

As output, we receive all keys or values set in the Map asciiConversion in an Iterable.

6. Conclusion

To sum up, this article shows how a Map works in Scala and how to iterate over the keys and values quickly.

As usual, the sample code used in this tutorial is available over on GitHub.