如何在 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 所暗示的那样,它旨在确保IterableList(就像toString 和许多其他to&lt;type&gt; 方法一样)。没有任何东西可以保证它会成为一个列表。例如,在扩展的开头添加以下行: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&lt;T&gt;().also it.addAll(this) 【参考方案7】:

对于浅拷贝,我建议

.mapit

这适用于许多集合类型。

【讨论】:

请注意,它不适用于Maps。它可以编译,但由于 itMap.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&lt;String&gt;。如果您不想暴露这个新列表的可变性,可以将类型显式声明为不可变列表:

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

【讨论】:

【参考方案11】:

在尝试了浅拷贝、深拷贝克隆等等之后,我发现这个解决方案肯定对你有用。

val iterator: Iterator<Object> = yourList.iterator()
        while (iterator.hasNext())
        newList.add(iterator.next().copy())

【讨论】:

【参考方案12】:

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

但是,它仅适用于浅层列表。

以下函数适用于任何二维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

【讨论】:

【参考方案13】:
var oldList: List<ClassA>?
val newList = oldList.map  it.copy() 

【讨论】:

【参考方案14】:

尝试下面的代码在 Kotlin

中复制列表
arrayList2.addAll(arrayList1.filterNotNull())

【讨论】:

这不会复制一个列表,它只是将一个列表添加到一个现有列表中(因此结果将是 ArrayList>)。

以上是关于如何在 kotlin 中克隆或复制列表的主要内容,如果未能解决你的问题,请参考以下文章

克隆 JavaScript 对象时如何排除键列表? [复制]

如何在 Java 中复制或克隆链表实现队列?

如何在 Oracle 中将一个用户复制或克隆到另一个用户

如何在不克隆的情况下复制 List<T>

如何在不使用复制或克隆的情况下克隆Rust中的结构?

如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]