什么是在 Kotlin 中复制 Map 的最聪明方法?

62

我希望获得一个新的Map实例,其内容与原始实例相同,但是Map没有内置的copy方法。 我可以像这样做:

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

但是它看起来相当丑陋。有没有更聪明的方法来做到这一点?


这非常低效,会分配大量临时对象。 - voddan
3
我知道,这就是为什么我提出了这个问题的原因。 - N. Kudryavtsev
1
我觉得这是一个bug:https://youtrack.jetbrains.com/issue/KT-11221 - voddan
4个回答

113

只需使用 HashMap 构造函数:

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

Kotlin 1.1更新:

自Kotlin 1.1起,扩展函数Map.toMapMap.toMutableMap将创建副本。


谢谢!它对于不可变的映射无效,但对于可变的映射仍然很棒。 - N. Kudryavtsev
3
如果您希望结果是只读类型,请手动声明该类型或使用转换:val copy : Map<Int,String> = HashMap(original)val copy = HashMap(original) as Map<Int, String>。如果您需要经常这样做,请编写一个扩展函数。 - Kirill Rakhman
3
地图不是不可变的,它们只是从只读接口访问。因此,如果最终使用一个只读变量来持有它,上面的示例就可以工作。 - Jayson Minard
但是他的解决方案对于映射的映射并不起作用。 - user3863488

9

使用 putAll 方法:

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

或者:

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

你的方式对我来说也很符合惯用语。

1
谢谢你的回答!显然,你想说 val copy = hashMapOf<String, Int>(); copy.putAll(map),因为 putAll 返回 Unit。当然,这比我的代码看起来更好,但它是一个 Java 方法,需要多于一行,并且不能用于不可变映射.. 这真的是最好的方法吗? - N. Kudryavtsev
我已经更正了这个例子。我认为调用Java方法没有问题,但如果对于你的情况不变性很重要,那么你的方法看起来更好。 - marcospereira
调用Java方法本身并不是问题,问题在于原始操作需要在被定位为Scala的简单替代语言中占用多行代码时。你的第二个变体要好得多。我认为对于不可变对象来说,现在这是最好的变体,所以再次感谢你!目前对我来说,不可变性并不重要,我只是感兴趣而已。 - N. Kudryavtsev
因为加号 + 而点赞。 - AlikElzin-kilaka

2
提议的做法是:
map.toList().toMap()

然而,Java的方法速度是2到3倍更快:
(map as LinkedHashMap).clone()

无论如何,如果你觉得 Kotlin 的集合没有统一的克隆方式有点麻烦(Java 中是有的!),请在这里投票:https://youtrack.jetbrains.com/issue/KT-11221


1
添加此扩展名(将条目转换为对)
val <K, V> Map<K, V>.pairs: Array<Pair<K, V>>
    get() = entries.map { it.toPair() }.toTypedArray()

然后,您可以使用默认的Kotlin语法轻松组合不可变映射。
val map1 = mapOf("first" to 1)
val map2 = mapOf("second" to 2)
val map3 = mapOf(
    *map1.pairs,
    "third" to 3,
    *map2.pairs,
)

1
什么、什么、什么?这看起来很不错。你能解释一下扩展和用法吗? - AlikElzin-kilaka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接