android – Deep copy of list with objects in Kotlin-ThrowExceptions

Exception or error:

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)
How to solve:

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)]

###

Use ‘to’ for iterate object

List -> toList()

Array -> toArray()

ArrayList -> toArray()

MutableList -> toMutableList()


Example:

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())

print log:

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

###

You can create an extension function that you can then use on ArrayList objects:

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

Usage:

arrayList.copy()

If you’re not using Ints in your target ArrayList, just change it in the extension function.

###

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)) }

###

There is no default function in Kotlin to do this.
I have done using 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"

It will not update the originaList.
Changes will only reflect in the copiedList.

Leave a Reply

Your email address will not be published. Required fields are marked *