0
votes

In Kotlin it is possible to use bracket notation with a Map, so the following code:

  val mapOfMap: Map<String, Map<String, String>> = mapOf("Key1" to mapOf("Subkey1" to "Value1", "Subkey2" to "Value2"))
  println(mapOfMap["Key1"])

prints:

{Subkey1=Value1, Subkey2=Value2}

That's great. But why can't I do the following

println(mapOfMap["Key1"]["Subkey1"])

It causes a compilation error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Map?

What is the proper way to handle this?

2

2 Answers

3
votes

mapOfMap["Key1"] returns Map<String, String>?, and get operator isn't specified for nullable Map. Therefore, the following code does not compile:

mapOfMap["Key1"]["Subkey1"]

You can make it compile by creating extension get operator function with nullable Map receiver:

operator fun <K, V> Map<K, V>?.get(key: K): V? = this?.get(key)

You can also create an extension get operator function for maps of maps:

operator fun <K1, K2, V> Map<K1, Map<K2, V>>.get(key1: K1, key2: K2): V? = get(key1)?.get(key2)

And use it this way:

mapOfMap["Key1", "Subkey1"]
3
votes

Because mapOfMap["Key1"] could return null, since it cannot guess if the desired key is in the map or not. It's the same as calling mapOfMap.get("Key1"). The second map can be null, thus it cannot call another .get() on it. You can do this instead: mapOfMap["Key1"]?.get("Subkey1")