Iterating over a Map in Scala
Iterating over a map is slightly more complex than over other collections, because a Map is the combination of 2 collections. The keys and the values.
val m: Map[Int, String] = Map(1 -> "a", 2 -> "b")
m.keys // = Iterable[Int] = Set(1, 2)
m.values // = Iterable[String] = MapLike("a", "b")
We make a Map using tuples. -> is just syntactic sugar for making a tuple.
val x = 1 -> 2 // = (Int, Int) = (1,2)
val y = (1, 2) // = (Int, Int) = (1,2)
x == y // = Boolean = true
Map((1, "a"), (2, "b")) == Map(1 -> "a", 2 -> "b") // = Boolean = true
We get these tuples when we iterate over a Map.
m.foreach { a: (Int, String) =>
println(s"$a")
}
prints
(1,a)
(2,b)
To get the key and the value we could use _1 and _2
m.foreach { a: (Int, String) =>
val key = a._1
val value = a._2
println(s"key:$key value:$value")
}
But this looks confusing. It's better to unpack it using case.
m.foreach { case (k, v) =>
println(s"key:$k value:$v")
}
We can use map to change the keys of a Map.
m.map { case (k, v) =>
k + 1 -> v
}
// = Map[Int,String] = Map(2 -> "a", 3 -> "b")
If we just want to change the values, it's better to use mapValues.
m.mapValues { v => v + v }
// = Map[Int,String] = Map(1 -> "aa", 2 -> "bb")
And of course our favorite method, flatMap, also works on Maps.
m.flatMap { case (k, v) =>
Map(k -> v, k + 10 -> v)
}
// = Map[Int,String] = Map(1 -> "a", 11 -> "a", 2 -> "b", 12 -> "b")