如何在 kotlin 中克隆或复制列表
Posted
技术标签:
【中文标题】如何在 kotlin 中克隆或复制列表【英文标题】:How to clone or copy a list in kotlin 【发布时间】:2018-04-01 10:38:55 【问题描述】:如何在 Kotlin 中复制列表?
我正在使用
val selectedSeries = mutableListOf<String>()
selectedSeries.addAll(series)
有没有更简单的方法?
【问题讨论】:
我认为您的解决方案已经是最简单的方法了,以防您不需要深度克隆。 复制列表只是复制对项目的引用。项目本身不会克隆。如果您希望深度克隆列表,请不要忘记在复制列表期间克隆项目。 【参考方案1】:这很好用。
val selectedSeries = series.toMutableList()
【讨论】:
val selectedSeries = series.toList()
也有效,因为它在实现中调用了toMutableList()
。
@FlávioFaria 刚刚用===
对其进行了测试,不得不说toList()
不会复制集合,但toMutableList()
会
@PeppermintPaddy 它确实复制,除非是空列表。如果源为空,Iterable.toList()
返回emptyList()
,它总是返回相同的(不可变的)对象。因此,如果您使用 emptyList()
进行测试,您将得到相同的对象。
这不是一个好的答案,也绝对不是正确的答案,不能保证未来的实现可能会改变,除非它特别记录了此方法调用将始终返回一个新副本。
@BrunoJCM,情况不再如此。 Kotlin 文档指出 toMutableList()
返回一个 new 列表,“返回一个新的 MutableList,其中填充了该集合的所有元素。”。【参考方案2】:
你可以使用
列表 -> 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
【讨论】:
【参考方案3】:如果您的列表持有kotlin data class,您可以这样做
selectedSeries = ArrayList(series.map it.copy() )
【讨论】:
如果您只想将arraylist的1个属性复制到另一个arraylist怎么办? 最佳响应。谢谢。所有其他人都没有工作 如果你想要mutableList
,你可以使用selectedSeries = series.map it.copy() .toMutableList()
【参考方案4】:
我可以想出两种替代方法:
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。有关新类型推理的更多信息,请观看此视频:KotlinConf 2018 - New Type Inference and Related Language Features by Svetlana Isakova,尤其是 30 岁时的“构建者推理”
【讨论】:
应该分成2个答案恕我直言,因为我认为第一个是正确的,但后者缺乏一些美感。 @Jacob Wu:我很惊讶地看到第二个解决方案中的 * 符号没有产生错误。它有什么作用?我用“一元乘法”进行了搜索,但没有找到任何东西。 @Lensflare * 表示将数组分解为单独的项目,例如mutableListOf( * [1, 2, 3] ) 表示 mutableListOf(1, 2, 3),相当于 vararg 的相反操作 @Jacob Wu:谢谢。通过您的回答,我发现该运算符称为“扩展运算符”。我通过将一些参数与数组组合到可变参数列表中来了解它的帮助。但是在您的示例中它有什么好处?是更快还是什么?还是确保收藏被复制的关键? @Lensflare 我认为好处只是语法 - 代码很短,并且不需要显式的泛型类型(就像我的第一个示例一样)。在幕后,我相信代码编译为数组操作,所以性能应该是一样的。【参考方案5】:就像在 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 的复制构造函数。
【讨论】:
【参考方案6】:您可以使用提供的扩展名Iterable.toMutableList()
,它将为您提供一个新列表。不幸的是,正如它的签名和documentation 所暗示的那样,它旨在确保Iterable
是List
(就像toString
和许多其他to<type>
方法一样)。没有任何东西可以保证它会成为一个新列表。例如,在扩展的开头添加以下行:if (this is List) return this
是一种合法的性能改进(如果它确实提高了性能)。
另外,由于它的名字,生成的代码不是很清楚。
我更喜欢添加自己的扩展来确保结果并创建更清晰的代码(就像我们为 arrays 所做的那样):
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
是最快的复制方式,因为它在ArrayList
的实现中使用了原生的System.arraycopy
。
另外,请注意,这只会给您一个shallow copy。
编辑:
您可能想要使用更通用的版本:
fun <T> Collection<T>.copyOf(): Collection<T>
val original = this
return mutableListOf<T>().apply addAll(original)
fun <T> Collection<T>.mutableCopyOf(): MutableCollection<T>
val original = this
return mutableListOf<T>().apply addAll(original)
【讨论】:
我喜欢这个解决方案。不应该是addAll(this@copyOf)
,因为this
里面apply
会引用新创建的空列表?是那个还是mutableListOf<T>().also it.addAll(this)
?【参考方案7】:
对于浅拷贝,我建议
.mapit
这适用于许多集合类型。
【讨论】:
请注意,它不适用于Map
s。它可以编译,但由于 it
是 Map.Entry
,并且副本很浅,因此您有相同的条目。
@noamtm 是的,这就是我所说的浅拷贝。此方法永远不会复制条目。它只会制作具有相同条目的集合的副本。地图在这里没什么特别的。
我的意思是,尽管它也很想在地图上使用它,而且它可以编译并且似乎可以工作 - 它并没有真正工作。【参考方案8】:
您可以使用ArrayList
构造函数:ArrayList(list)
【讨论】:
【参考方案9】:val selectedSeries = listOf(*series.toTypedArray())
【讨论】:
【参考方案10】:我会使用the toCollection()
extension method:
val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())
这将创建一个新的MutableList
,然后将原始的每个元素添加到新创建的列表中。
这里推断的类型将是MutableList<String>
。如果您不想暴露这个新列表的可变性,可以将类型显式声明为不可变列表:
val copy: List<String> = original.toCollection(mutableListOf())
【讨论】:
【参考方案11】:在尝试了浅拷贝、深拷贝克隆等等之后,我发现这个解决方案肯定对你有用。
val iterator: Iterator<Object> = yourList.iterator()
while (iterator.hasNext())
newList.add(iterator.next().copy())
【讨论】:
【参考方案12】:对于简单的列表,上面有很多正确的解决方案。
但是,它仅适用于浅层列表。
以下函数适用于任何二维ArrayList
。 ArrayList
实际上等同于 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
【讨论】:
【参考方案13】:var oldList: List<ClassA>?
val newList = oldList.map it.copy()
【讨论】:
【参考方案14】:尝试下面的代码在 Kotlin
中复制列表arrayList2.addAll(arrayList1.filterNotNull())
【讨论】:
这不会复制一个列表,它只是将一个列表添加到一个现有列表中(因此结果将是 ArrayList>)。以上是关于如何在 kotlin 中克隆或复制列表的主要内容,如果未能解决你的问题,请参考以下文章
克隆 JavaScript 对象时如何排除键列表? [复制]
如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]