61

I'd like to get a new instance of some Map with the same content but Map doesn't have a built-in copy method. I can do something like this:

val newInst = someMap.map { it.toPair() }.toMap()

But it looks rather ugly. Is there any more smarter way to do this?

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
N. Kudryavtsev
  • 3,556
  • 1
  • 26
  • 30

4 Answers4

111

Just use the HashMap constructor:

val original = hashMapOf(1 to "x")
val copy = HashMap(original)

Update for Kotlin 1.1:

Since Kotlin 1.1, the extension functions Map.toMap and Map.toMutableMap create copies.

Ingo Kegel
  • 46,523
  • 10
  • 71
  • 102
  • Thank you! It doesn't work for immutable maps, but is still great for mutable ones. – N. Kudryavtsev Feb 27 '16 at 17:57
  • 3
    If you want the result to be of read-only type, declare the type manually or use a cast: `val copy : Map = HashMap(original)` or `val copy = HashMap(original) as Map`. If you do this repeatedly, write an extension function. – Kirill Rakhman Feb 28 '16 at 13:39
  • 3
    @N.Kudriavtsev maps are not immutable, they are just accessed from a readonly interface. So the example above does work if you hold it with a readonly variable in the end. – Jayson Minard Feb 28 '16 at 14:42
  • Butt his solution not working for map of maps. – user3863488 Feb 27 '23 at 06:22
9

Use putAll method:

val map = mapOf("1" to 1, "2" to 2)
val copy = hashMapOf<String, Int>()
copy.putAll(map)

Or:

val map = mapOf("1" to 1, "2" to 2)
val copy = map + mapOf<String, Int>() // preset

Your way also looks idiomatic to me.

marcospereira
  • 12,045
  • 3
  • 46
  • 52
  • 1
    Thank you for your answer! Obviously, you'd like to say `val copy = hashMapOf(); copy.putAll(map)` because putAll returns Unit. Of course it looks better than my code, however, it is a Java method, takes more than one line and doesn't work with immutable maps.. Is it really the best way? – N. Kudryavtsev Feb 27 '16 at 16:41
  • I've corrected the example. I don't see an problem with calling a Java method, but immutability is important for your case, then your method looks better. – marcospereira Feb 27 '16 at 17:04
  • Calling a Java method is not a problem itself, the problem is when the primitive operation requires more than one line of code in a language that was positioned as a simple alternative for Scala. Your second variant is much better. And I think for now it is the best variant for immutables, so thank you once again! Immutability is not important for me right now, I was just interested. – N. Kudryavtsev Feb 27 '16 at 18:27
  • Upvoted for the `+` (plus) – AlikElzin-kilaka Jun 07 '22 at 13:43
2

The proposed way of doing this is:

map.toList().toMap()

However, the java's method is 2 to 3 times faster:

(map as LinkedHashMap).clone()

Anyway, if it bothers you that there is no unified way of cloning Kotlin's collections (and there is in Java!), vote here: https://youtrack.jetbrains.com/issue/KT-11221

voddan
  • 31,956
  • 8
  • 77
  • 87
1

Add this extension (to convert entries to pairs)

val <K, V> Map<K, V>.pairs: Array<Pair<K, V>>
    get() = entries.map { it.toPair() }.toTypedArray()

And then you can easy combine immutable maps using default Kotlin syntax.

val map1 = mapOf("first" to 1)
val map2 = mapOf("second" to 2)
val map3 = mapOf(
    *map1.pairs,
    "third" to 3,
    *map2.pairs,
)
Pavel Shorokhov
  • 4,485
  • 1
  • 35
  • 44