如何在Kotlin中克隆或复制列表


102

如何在Kotlin中复制列表?

我正在使用

val selectedSeries = mutableListOf<String>()
selectedSeries.addAll(series)

有没有更简单的方法?


1
我认为您的解决方案已经是最简单的方法,以防您不需要深度克隆。
SerdarSamancıoğlu,

Answers:


145

这很好。

val selectedSeries = series.toMutableList()

6
val selectedSeries = series.toList()之所以起作用,是因为它要求toMutableList()实现。
弗拉维奥法利亚

4
@FlávioFaria刚刚对其进行了测试===,不得不说不toList()复制该收藏,但是toMutableList()会复制
Peppermint Paddy

3
@PeppermintPaddy 确实会复制,除非是空列表。如果源为空,则Iterable.toList()返回emptyList(),始终返回相同(不可变)的对象。因此,如果进行测试,emptyList()您将获得相同的对象。
劳伦斯·贡萨尔维斯

52
我个人不喜欢这个主意... toMutableList()如果调用该方法的实例已经是可变列表,则文档授予中的任何内容都不应返回列表的新实例。
BrunoJCM

4
这不是一个好的答案,而且绝对不是正确的答案,除非特别说明该方法调用将始终返回新副本,否则无法保证将来的实现可能会更改。
巴尔加夫

23

您可以使用

列表-> toList()

数组-> toArray()

ArrayList-> toArray()

MutableList-> toMutableList()


例:

val array = arrayListOf("1", "2", "3", "4")

val arrayCopy = array.toArray() // copy array to other array

Log.i("---> array " ,  array?.count().toString())
Log.i("---> arrayCopy " ,  arrayCopy?.count().toString())

array.removeAt(0) // remove first item in array 

Log.i("---> array after remove" ,  array?.count().toString())
Log.i("---> arrayCopy after remove" ,  arrayCopy?.count().toString())

打印日志:

array: 4
arrayCopy: 4
array after remove: 3
arrayCopy after remove: 4

14

我可以提出两种替代方法:

1. val selectedSeries = mutableListOf<String>().apply { addAll(series) }

2. val selectedSeries = mutableListOf(*series.toTypedArray())

更新:使用新的类型推断引擎(在Kotlin 1.3中启用),我们可以在第一个示例中省略泛型类型参数,并具有以下功能:

1. val selectedSeries = mutableListOf().apply { addAll(series) }

仅供参考,选择新推理的方法是kotlinc -Xnew-inference ./SourceCode.kt命令行或kotlin { experimental { newInference 'enable'}Gradle。有关新类型推断的更多信息,请观看以下视频:Svetlana Isakova撰写的KotlinConf 2018-新型类型推断和相关语言功能,特别是30岁的``建筑商的推断''


应将答案分为2个答案,恕我直言,因为我认为第一个是正确的,但后者缺乏某些美感。
霍尔格·布兰德尔'18

@Jacob Wu:我很惊讶地看到第二个解决方案中的*符号没有产生错误。它有什么作用?我使用“一元乘法”进行搜索,但未找到任何内容。
Lensflare

1
@Lensflare *表示将数组分解为单独的项,例如mutableListOf(* [1、2、3])表示mutableListOf(1、2、3),就像vararg的相反操作
Jacob Wu

1
@Jacob Wu:谢谢。通过您的回答,我发现该运算符被称为“扩展运算符”。我看到了如何通过将一些参数与数组组合到varargs列表中来提供帮助。但是,在您的示例中它有什么好处?是更快还是什么?还是确保复制收藏集的关键?
Lensflare

@Lensflare我认为好处只是语法-代码简短,不需要显式的泛型(例如在我的第一个示例中)。在后台,我相信代码被编译为数组操作,因此性能应该相同。
Jacob Jacob


9

您可以使用提供的扩展名Iterable.toMutableList(),这将为您提供一个新列表。不幸的是,正如其签名和文档所暗示的那样,它旨在确保an Iterable是一个ListtoString与其他许多to<type>方法一样)。没有什么可以保证您将成为一个新的清单。例如,在扩展名的开头添加以下行:if (this is List) return this是合理的性能改进(如果确实可以提高性能)。

另外,由于其名称,生成的代码也不是很清楚。

我更喜欢添加自己的扩展名以确保结果并创建更清晰的代码(就像我们对array一样):

fun <T> List<T>.copyOf(): List<T> {
    val original = this
    return mutableListOf<T>().apply { addAll(original) }
}

fun <T> List<T>.mutableCopyOf(): MutableList<T> {
    val original = this
    return mutableListOf<T>().apply { addAll(original) }
}

请注意,这addAll是最快的复制方法,因为它System.arraycopy在的实现中使用本机ArrayList

另外,请注意,这只会给您浅表的副本


我喜欢这个解决方案。不应该addAll(this@copyOf),因为this内部apply将引用新创建的空列表吗?还是那个mutableListOf<T>().also { it.addAll(this) }
Franko LeonTokalić

5

对于浅表副本,我建议

.map{it}

这将适用于许多集合类型。


1
请注意,它不适用于Map。它可以编译,但是由于itMap.Entry,并且副本很浅,因此您具有相同的条目。
noamtm

1
@noamtm是的,这就是我浅拷贝的意思。此方法将永远不会复制条目。它只会复制具有相同条目的集合。地图在这里没什么特别的。
Lensflare

2
我的观点是,即使它也很想在地图上使用它,并且它可以编译并且似乎可以工作-但这实际上并没有工作。
noamtm

4

就像在Java中一样:

清单:

    val list = mutableListOf("a", "b", "c")
    val list2 = ArrayList(list)

地图:

    val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
    val map2 = HashMap(map)

假设您以JVM(或Android)为目标;我不确定它是否适用于其他目标,因为它依赖于ArrayList和HashMap的副本构造函数。


2

我会使用toCollection()扩展方法

val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())

这将创建一个新MutableList元素,然后将原始元素的每个元素添加到新创建的列表中。

推断的类型将是MutableList<String>。如果您不想公开此新列表的可变性,则可以将类型显式声明为不可变列表:

val copy: List<String> = original.toCollection(mutableListOf())

0

对于简单的列表,上面有许多正确的解决方案。

但是,它仅用于浅表。

以下函数适用于任何二维ArrayListArrayList实际上等于MutableList。有趣的是,在使用显式MutableList类型时它不起作用。如果需要更多尺寸,则有必要增加功能。

fun <T>cloneMatrix(v:ArrayList<ArrayList<T>>):ArrayList<ArrayList<T>>{
  var MatrResult = ArrayList<ArrayList<T>>()
  for (i in v.indices) MatrResult.add(v[i].clone() as ArrayList<T>)
  return MatrResult
}

整数矩阵演示:

var mat = arrayListOf(arrayListOf<Int>(1,2),arrayListOf<Int>(3,12))
var mat2 = ArrayList<ArrayList<Int>>()
mat2 = cloneMatrix<Int>(mat)
mat2[1][1]=5
println(mat[1][1])

表明 12



-1

尝试下面的代码在Kotlin中复制列表

arrayList2.addAll(arrayList1.filterNotNull())
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.