Looking up a value by its key
To read a value from a map, put its key in square brackets after the map's name:
val scores = mutableMapOf("Alice" to 95, "Bob" to 87)
val aliceScore = scores["Alice"] // 95
val bobScore = scores["Bob"] // 87
The brackets call the map's get function, so scores["Alice"] and scores.get("Alice") do the same thing. The bracket form is the one Kotlin code normally uses.
The result may be missing
A key you ask for may not be in the map. Kotlin does not throw in that case. It returns null:
println(scores["Diana"]) // null
Because of that, the type of scores["Alice"] is not Int but Int?, a nullable integer. The question mark means "an Int, or null". The compiler tracks this for you, and it will not let you use an Int? where a plain Int is required, for example in arithmetic:
val total = scores["Alice"] + 5 // does not compile: the value may be null
You have to say what should happen when the key is missing. Kotlin gives you several ways to say it.
Four ways to deal with a missing key
1. Assert it is there with !!
The operator !! tells the compiler "I know this is not null". The result has the plain type Int:
val aliceScore = scores["Alice"]!! // Int
If the key turns out to be missing, !! throws a NullPointerException and the program stops. Use it only when you are certain the key exists, as in this lesson, where "Alice" is in the map two lines above.
2. Supply a default with ?:
The operator ?: gives a fallback for the null case:
val score = scores["Diana"] ?: 0 // 0
If the left side is not null, its value is used. Otherwise, the right side is. The result is a plain Int.
3. Use getOrDefault
On the JVM, a map also offers getOrDefault(key, default), which returns the default when the key is missing:
val score = scores.getOrDefault("Diana", 0) // 0
4. Use getValue
The function getValue returns a plain value and throws a NoSuchElementException when the key is missing. The message names the key: Key Diana is missing in the map. It fails with a clearer error than !! does, which is useful when a missing key means a bug.
Checking whether a key exists
When you only need to know if a key is present, use containsKey or the shorter in operator:
if (scores.containsKey("Alice")) {
println(scores["Alice"])
}
println("Alice" in scores) // true
Checking with in and then reading the value works, but it looks the key up twice. When you want both the check and the value, scores["Alice"] ?: 0 or an if (value != null) test on the result of a single lookup is shorter.
Getting all keys or all values
Sometimes you want every key or every value rather than one lookup. A map exposes them as properties:
println(scores.keys) // [Alice, Bob]
println(scores.values) // [95, 87]
These are views of the map's current contents, and you can loop over them like any other collection. Looking up by key is what a map is fast at, so prefer scores["Alice"] to searching through values.
The exercise
The starting code already has a map:
val scores = mutableMapOf("Alice" to 95, "Bob" to 87, "Charlie" to 72)
The task is to declare a new val named aliceScore that holds Alice's score. Look up the key with scores["Alice"]. That gives an Int?, so add !! to turn it into an Int. The key is in the map, so the assertion is safe:
val scores = mutableMapOf("Alice" to 95, "Bob" to 87, "Charlie" to 72)
val aliceScore = scores["Alice"]!!
Now aliceScore is the integer 95.
Common mistakes
- Wrong capitalisation. Keys are compared exactly, so
scores["alice"]is notscores["Alice"]. The first returnsnull. - Using
!!on a key that may be absent. The program crashes with aNullPointerException. Use?:when a missing key is possible. - Using parentheses. Lookups are written
scores["Alice"], with square brackets.scores("Alice")does not compile. - Treating the value as a plain number. Arithmetic on
scores["Alice"]does not compile until you deal with the null case.
Key takeaways
map[key]returns the value, ornullif the key is missing, so its type is nullable.!!asserts the value exists and throws if it does not;?: defaultsupplies a fallback.getOrDefault,getValue,containsKeyandincover the other common needs.