Search code examples
dictionarykotlindata-structuresimmutability

Kotlin standard approach of making new map from an immutable map and additional key-value


Is there a standard way in Kotlin to associate a new key-value pair with an immutable map?

// => {A=1, B=2, C=3}
associate(mapOf("A" to 1, "B" to 2), "C", 3);

Thinking about something similar to assoc function in Clojure.

;;=> { :key1 "value1", :key2 "value2", :key3 "value3"}
(assoc {:key1 "value1" :key2 "value2"} :key3 "value3")

It is obvious how to make it directly copying entries into a new map, but I believe there is more optimal approach implemented in the Kotlin standard library. Could you give an example of making this idiomatically?


Solution

  • This is done using the plus operator.

    val map1 = mapOf("A" to 1, "B" to 2)
    val map2 = map1 + ("C" to 3)
    
    // or for a read-write variable/property:
    var map = mapOf("A" to 1, "B" to 2)
    map += "C" to 3
    

    If you want to add more than one item at once, you can put any collection or array of pairs after the plus sign:

    val map1 = mapOf("A" to 1, "B" to 2)
    val map2 = map1 + arrayOf("C" to 3, "D" to 4)
    

    Note that the correct terminology for a Map is “read-only” map, not “immutable” map. A Map is often a MutableMap under the hood that has been cast to a read-only Map, so it is not actually immutable. There is a common pattern in Kotlin of a class exposing access to a mutable collection through a property that upcasts it to a read-only implementation but continues to mutate that reference for the outside classes to observe changes.