Basic data structures in Scala: Maps
After Lists and tuples, let’s have a look at Maps.
They are sometimes called “hashtables”, “hashes”, or “dictionaries” in other programming languages.
Maps are a bit more complex than what we’ve seen before. They come handy when you need to store associated pairs of data, or when you need to easily look up a value corresponding to another value (which we will call the key).
It does matter (as with Lists) what kind of objects you want to store as keys and as values. You can pick a type for each.
Creating a Map
Scala offers a simple syntax to create an immutable Map filled with some key-value pairs:
val tweetMap = Map(
414 -> "#scaladays are coming to Berlin!",
435 -> "Scala is the new golden child",
506 -> "#scaladays Scaladex: scala package index")
val justAMap = Map(11 -> "hello", 13 -> 3.56)
val notValidMap: Map[Int, Double] = Map(63 -> 6.3, 19 -> "hello")
val emptyMap = Map()
The third example above will give an “error: type mismatch”, because we specified that we want to stores Ints and Doubles in the map, but we tried to stuff in a String as a value. Scala doesn’t let that happen.
Looking up a value for a key
If you are coming from the Java world, your instinct might tell you to call a get(key) function on the map to access the corresponding value. It works, but probably in a bit different way than you would expect.
tweetMap.get(414)
// will return:
// Some("#scaladays are coming to Berlin!")
The get(key) function returns an Option which is a special type, that I will explain in the next post.
For now, let’s use another, simpler way to access the value that belongs to a key:
tweetMap(414)
// will return the String:
// "#scaladays are coming to Berlin!"
Using mutable Maps
Until now we had maps that were immutable. Because Scala, by default, imports “scala.collection.immutable.Map” as “Map”.
But if we want to extend, or otherwise modify the contents of a map, we will need a mutable Map. And we have to import it by:
import scala.collection.mutable.Map
If you want to use both kinds of maps, then you can import both, and give them your own names like this:
import scala.collection.immutable.{Map => ImmuMap}
import scala.collection.mutable.{Map => MuMap}
val todoMap: MuMap[Int, String] = MuMap()
todoMap += (1 -> "think")
todoMap += (2 -> "write")
todoMap += (3 -> "publish")
In the example above we created a MuMap, which was empty at first, but then we added three pairs using the “+=” operator and specifying the key-value pairs (those were separated by simple arrows: “->”).
Iterating over all elements of a Map
For this we can either use an iterator:
val mIter = todoMap.iterator
while (mIter.hasNext) { println(mIter.next) }
This will print the tuples:
(2,write)
(1,think)
(3,publish)
Or, we could use the foreach method of the Map:
todoMap.foreach(kv => println("key: " + kv._1 + ", value: " + kv._2))
To see this output:
key: 2, value: write
key: 1, value: think
key: 3, value: publish
Summary and other sources
This page of TutorialsPoint lists more operations on Scala Maps.
Scala offers more Map implementations, with different trade-offs regarding mutability, speed of operations, ordering, etc. If you need advice on which one to choose, this guide might help.
Some runnable code examples are here.
Next time I’ll briefly cover Scala’s special collection-like tool: Option.
Note: If you want to learn about Scala’s “map()” function, with which you can simply apply a function on each element of a list, then you have to wait for a yet-to-come post. Alternatively, read this.