Deep copy of list with objects in Kotlin
Asked Answered
M

3

45

I am new to kotlin and I am trying to make a copy of a list of objects.The problem I am having is that when I change items in the new copy, the old list gets changed as well. This is the object:

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

I tried doing this, but it doesn't work:

val oldList:ArrayList<ClassA>


val newList :ArrayList<ClassA> = ArrayList()
newList.addAll(oldList)
Maximilianus answered 23/7, 2018 at 13:32 Comment(1)
check this https://mcmap.net/q/116576/-how-to-clone-or-copy-a-list-in-kotlinKarie
B
58

That's bacause you are adding all the object references to another list, hence you are not making a proper copy, you have the same elements in two list. If you want diferents list and diferent references, you must clone every object in a new list:

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)]
Bone answered 23/7, 2018 at 13:36 Comment(7)
Hey @Dam, What if the class is not a data class? How do I clone with different hashcode?Fiat
it saves my day. alhamdulillahDemonic
Would this do a deep copy?Blakeslee
@Blakeslee This will only deep copy known class members. And even this answer has a flow. All objects in the List are "deep copied" but not the List reference itself. List still points to the same memory location, only its content has been changed. If you add another list to your class and forget to apply the same steps mentioned here to the new List, you'll still have a headache. So no, this is not a generic deep copy solution, just a solution (workaround) for specific use casesPhloem
it saved my lifeMatelda
Do I have to put .copy()? It works without the code. Why do I have to call copy() method?Coat
map function does not copy the listMcintyre
T
16
var oldList: List<ClassA>?

val newList = oldList.map { it.copy() }
Tavish answered 4/11, 2021 at 11:36 Comment(1)
I wasted a lot of time for this issue, thanks, you saved my day !!Karlynkarma
C
1

This is not related to kotlin, when you are adding the objects from the old list to the new one, it add the reference to them (no createing a new object ), whats mean it just copying the address in the memory to the new list.

To fix this problem you should create a new instance for each object. you can create a copy constructor, for example:

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

and then add them one by one to the new list:

list1.forEach { list2.add(Class(it)) }
Chilton answered 23/7, 2018 at 13:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.