Reading a value by its key
To read a value from a Scala Map, write the key in parentheses after the map's name. Unlike an array, where the parentheses hold a position, here they hold the key:
val ages = Map("Ana" -> 12, "Ben" -> 15)
println(ages("Ben")) // 15
The same syntax works for a mutable map, which is what the lesson uses:
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
println(scores("Bob")) // 87
The result has the map's value type, here Int, so you can use it directly in arithmetic: scores("Bob") + 3 is 90.
The exercise
The starting code already has the scores map. The task is to read Alice's score into a new val named aliceScore.
- Declare
val aliceScore. - Assign
scores("Alice"). The key must match exactly, including the capitalA.
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
val aliceScore = scores("Alice")
Now aliceScore is the Int 95. It is a copy of the value: later changing the entry in the map doesn't change aliceScore, because an Int is a plain number.
When the key is missing
The parentheses form trusts you that the key exists. If it doesn't, the program stops with an exception:
println(scores("Dan"))
java.util.NoSuchElementException: key not found: Dan
When a key might be absent, use one of the safe forms instead:
scores.get("Dan")returns anOption[Int]:Some(95)for"Alice"andNonefor"Dan".scores.getOrElse("Dan", 0)returns the value, or the fallback0when the key is missing.scores.contains("Dan")returns aBoolean, so you can test before reading.
println(scores.get("Alice")) // Some(95)
println(scores.get("Dan")) // None
println(scores.getOrElse("Dan", 0)) // 0
println(scores.contains("Dan")) // false
Why lookups by key are useful
A map answers the question "what is the value for this key?" directly, without searching through the entries one by one. A mutable Map is backed by a hash table, so a lookup takes about the same time whether the map has three entries or three million. That is why a map is the usual choice when you repeatedly look things up by name, id or word, rather than by position.
The type of the key matters too. In a Map[String, Int] the key in the parentheses must be a String, and the compiler rejects anything else, such as scores(0), with a type error.
Reading everything in a map
Often you want all the entries, not one. A for loop can take each pair apart into a key and a value, and keys and values give each side on its own. Maps don't promise an order, so sort when you need a predictable one:
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
for ((name, score) <- scores.toList.sorted) {
println(s"$name: $score")
}
println(scores.keys.toList.sorted) // List(Alice, Bob, Charlie)
println(scores.values.toList.sorted) // List(72, 87, 95)
The loop prints Alice: 95, Bob: 87 and Charlie: 72, one per line. Here toList turns the map into a list of (key, value) pairs, and sorted orders them by key.
Common mistakes
- Using square brackets.
scores["Alice"]is not valid Scala. Maps, arrays and lists all use parentheses. - Wrong capitalisation or spelling. Keys are compared exactly, so
scores("alice")throws the samekey not foundexception. - Treating a key as an index. A map has no position numbers.
scores(0)looks for the key0, and withStringkeys it doesn't even compile. - Assuming
getreturns the value. It returns anOption. To get95itself, usegetOrElseor amatch.
Key takeaways
map(key)returns the value for the key and throwsNoSuchElementExceptionif the key is missing.get,getOrElseandcontainsare the safe ways to look up a key that may not exist.- Keys must match exactly.
