Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy Immutable Map to Mutable Map in Kotlin

Tags:

kotlin

If I have an immutableMap: Map<String, Int> and want to convert it to a mutableMap: MutableMap<String, Int>, what would be the best way to do that? There doesn't seem like any convenient way.

like image 539
spierce7 Avatar asked Jul 26 '16 15:07

spierce7


People also ask

How do I copy a map in Kotlin?

If you want the result to be of read-only type, declare the type manually or use a cast: val copy : Map<Int,String> = HashMap(original) or val copy = HashMap(original) as Map<Int, String> . If you do this repeatedly, write an extension function.

How do you add a mutable map to Kotlin?

To add a new key-value pair to a mutable map, use put() . When a new entry is put into a LinkedHashMap (the default map implementation), it is added so that it comes last when iterating the map. In sorted maps, the positions of new elements are defined by the order of their keys.

Is Kotlin map mutable?

In Kotlin, key/value pairs are called entries. It is important to note that Kotlin maps are immutable by default. This means that entries cannot be edited, deleted, or changed in any way after they have been created.

Is map immutable in Kotlin?

Kotlin Map : mapOf() Kotlin distinguishes between immutable and mutable maps. Immutable maps created with mapOf() means these are read-only and mutable maps created with mutableMapOf() means we can perform read and write both. The first value of the pair is the key and the second is the value of the corresponding key.


2 Answers

Update: The Kotlin 1.1 stdlib has a .toMutableMap() function. This should be used instead of creating your own.

----------------------- Old Answer Below ------------------------------

The following extension function works by copying the Map to a MutableMap.

fun <K, V> Map<K, V>.toMutableMap(): MutableMap<K, V> {
  return HashMap(this)
}

Some of the other answers suggest checking to see if the map is a MutableMap and then casting to it if it is. This should be avoided at all costs, as it's a bad practice. The fact that it was downcasted to a Map in Kotlin implies that it's expected that this Map shouldn't be changed, and it would be dangerous to do so.

like image 157
spierce7 Avatar answered Sep 18 '22 17:09

spierce7


First, as covered in previous questions about Kotlin read only collections and their immutability, they are really read only live views of likely mutable collections.

Kotlin CAN safely check the type for mutability for these since there are markers on the interfaces that let Kotlin know, for example:

// assuming some variable readOnlyMap of type Map<String, String>

val mutableMap: MutableMap<String, String> = if (readOnlyMap is MutableMap<*,*>) {
    readOnlyMap as MutableMap
} else {
    HashMap(readOnlyMap)
}

This is check internally calls TypeIntrinsics.isMutableMap and is a valid way to know if it is castable. There is no danger in the cast if you do this check first. You'll note the compiler is perfectly happy and without warnings. This could be dangerous if you don't intend to modify the same map being treated as read-only, but shows that you can cast for affect.

If you do not want the chance of modifying your original map, then of course always make a copy by simply calling constructor of HashMap with another Map, HashMap(readOnlyMap). Or make an extension function:

    fun <K, V> Map<K, V>.toMutableCopy() = HashMap(this)

and call it:

    val mutableMap = readOnlyMap.toMutableCopy()

And now you have your simple way.

See also:

  • Kotlin and Immutable Collections?
  • How to turn a Mutable Collection into an Immutable one
  • Kotlin Editing List
  • Kotlin Instantiate Immutable List
  • Klutter library Immutable wrappers
like image 45
3 revs, 2 users 93% Avatar answered Sep 20 '22 17:09

3 revs, 2 users 93%