Copy a Map in Kotlin (3 Ways Explained)

Alexey Karimov

When working with maps in Kotlin, there are situations where you need a copy of the original. This might be to avoid mutating the source map, to safely pass data to another function, or to store a stable snapshot of values.

If that’s the case, then you might be looking for how to copy a map in Kotlin. Copying a map creates a new map with the same entries. Kotlin offers several ways to do this, each suited to different needs, like mutability, reusability, or compatibility with Java collections.

Note: The code examples are pseudo and can’t be executed. They are meant to help you understand the concept clearly.

Method 1: Use toMap() for Immutable Copy

If you need a read-only copy of an existing map, toMap() is the simplest option. It creates a new map with the same key-value pairs but doesn’t allow modifications. 

This is useful when you want to pass a snapshot of the map to another part of your code, without exposing it to changes.

val original = mapOf("x" to 1, "y" to 2)
val copy = original.toMap()

The copy is a new map instance. You can read from it like any other map, but you can’t add or remove entries. If you try to modify it, the compiler will throw an error because it’s immutable.

Method 2: Use toMutableMap() for Editable Copy

If you need to modify the copied map by adding, updating, or removing entries, use toMutableMap() instead. This creates a new, mutable map with the same entries as the original. This is useful when the original data is a starting point, but you plan to change it.

val original = mapOf("a" to 10, "b" to 20)
val editableCopy = original.toMutableMap()
editableCopy["c"] = 30  // Safe to modify

The editableCopy is completely separate from the original. Changes to it won’t affect the source map.

Method 3: Use HashMap(source) (Java Interop) 

If you’re working in a Java-based environment or using Kotlin versions prior to 1.1, copying a map using the HashMap constructor is a practical option. It creates a new mutable map containing the same entries.

val source = mapOf("lang" to "Kotlin", "version" to "1.9")
val javaCopy = java.util.HashMap(source)

This is especially useful when interacting with Java APIs that expect a java.util.Map. It’s a full copy and safe to modify, just like toMutableMap().

Note: All of these methods create a shallow copy. The map itself is new, but the keys and values still point to the same objects as the original. If the values are mutable types (like lists or custom objects), changes to them will be reflected in both maps.

Wrapping Up: Handling Copies in Multithreaded Environments

Copying a map might seem simple, but in a multithreaded context, things can break. If one thread is reading from a map while another is modifying it, you could run into a ConcurrentModificationException.

To avoid this, consider using thread-safe map implementations like ConcurrentHashMap. This ensures safe reads and writes across multiple threads without needing manual synchronization.

For highly read-heavy scenarios, some libraries offer CopyOnWriteMap, which duplicates the map on each write operation. It is useful when reads are frequent but updates are rare.

Hence, choose your copy method based on mutability, thread context, and whether you need full isolation from the original map.