Start learning free

LESSON 102 OF 348 · DICTIONARIES

Accessing Dictionary Values in Kotlin: map[key] and Null Safety

Lesson Read the full explanation

In Java, you access values in a HashMap using the get(key) method:

val scores = mutableMapOf("Alice" to 95, "Bob" to 87)

val aliceScore = scores["Alice"]  // 95
val bobScore = scores["Bob"]      // 87

If the key doesn't exist, get() returns null. Use getOrDefault() to provide a fallback:

val score = scores.getOrDefault("Diana", 0)  // returns 0 if not found

Check if a key exists with containsKey():

if (scores.containsKey("Alice")) {
    println(scores["Alice"])
}

Assignment
Follow the Coding Tutorial and access Alice's score from scores!


Hint
Use scores.get("Alice") and assign it to aliceScore.

STEP 1 OF 1
    Ctrl + Enter to check

    KOTLIN · DICTIONARIES

    Accessing Dictionary Values in Kotlin, explained

    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 not scores["Alice"]. The first returns null.
    • Using !! on a key that may be absent. The program crashes with a NullPointerException. 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, or null if the key is missing, so its type is nullable.
    • !! asserts the value exists and throws if it does not; ?: default supplies a fallback.
    • getOrDefault, getValue, containsKey and in cover the other common needs.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free