在Kotlin中具有对象的列表的深层副本

时间:2018-07-23 13:32:20

标签: android kotlin kotlin-android-extensions kotlin-extension

我是Kotlin的新手,我正在尝试制作对象列表的副本。我遇到的问题是,当我更改新副本中的项目时,旧列表也会被更改。这是对象:

class ClassA(var title: String?, var list: ArrayList<ClassB>, var selected: Boolean)
class ClassB(val id: Int, val name: String) 

我尝试这样做,但是不起作用:

val oldList:ArrayList<ClassA>


val newList :ArrayList<ClassA> = ArrayList()
newList.addAll(oldList)

5 个答案:

答案 0 :(得分:5)

那是因为您要将所有对象引用添加到另一个列表,因此您没有进行适当的复制,因此两个列表中的元素相同。如果要使用不同列表和不同引用,则必须在新列表中克隆每个对象:

public data class Person(var n: String)

fun main(args: Array<String>) {
    //creates two instances
    var anna = Person("Anna")
    var Alex =Person("Alex")

    //add to list
    val names = arrayOf(anna , Alex)
    //generate a new real clone list
    val cloneNames = names.map{it.copy()}

    //modify first list
    cloneNames.get(0).n = "Another Anna clone"

    println(names.toList())
    println(cloneNames.toList())
}

[Person(n=Anna), Person(n=Alex)]
[Person(n=Another Anna clone), Person(n=Alex)]

答案 1 :(得分:0)

这与kotlin无关,当您将旧列表中的对象添加到新列表中时,它会添加对它们的引用(不创建新对象),这意味着它只是将内存中的地址复制到新列表。

要解决此问题,您应该为每个对象创建一个新实例。您可以创建一个副本构造函数,例如:

constructor(otherA: ClassA) {
    this.prop1 = otherA.prop1
    this.prop2 = otherA.prop2
    ...
} 

,然后将它们一个一个地添加到新列表中:

list1.forEach { list2.add(Class(it)) }

答案 2 :(得分:0)

使用'to'来迭代对象

列表-> toList()

Array-> toArray()

ArrayList-> toArray()

MutableList-> toMutableList()


示例:

val array:ArrayList<String> = ArrayList()
array.add("1")
array.add("2")
array.add("3")
array.add("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 :(得分:0)

您可以创建一个扩展函数,然后将其用于ArrayList对象:

fun ArrayList<Int>.copy() : ArrayList<Int> {
    val arr = ArrayList<Int>()
    for(i in this) {
        arr.add(i)
    }
    return arr
}

用法:

arrayList.copy()

如果您不在目标ArrayList中使用Ints,只需在扩展功能中对其进行更改。

答案 4 :(得分:0)

Kotlin中没有默认功能可以执行此操作。 我已经使用了Gson。

public data class Person{
  val id = 1
  val name = ""
  public Person copy(){
        String stringPerson = new Gson().toJson(this, Person.class);
        return new Gson().fromJson(stringPerson, Person.class);
    }
}

val persone = Person()
persone.id = 1
person.name = "ABC"
val originalList = ArrayList()
list1.add(persone)
val copiedList = originalList.map{it.copy()}
list2.get(0).name = "DEF"

它不会更新originaList。 更改将只反映在copyedList中。