Reputation: 849
following from here
below provided for the test case
@Test
fun testKotlinArrayCopy() {
data class Person(val name: String, var friends: List<Person>, var isHungry: Boolean = false)
val okyFriends = listOf(
Person(name = "Billy", friends = listOf()),
)
val peopleAtBlock1 : ArrayList<Person> = arrayListOf(
Person(name = "Oky", friends = okyFriends),
)
val peopleAtBlock2 : ArrayList<Person> = ArrayList(peopleAtBlock1.toMutableList())
peopleAtBlock1[0].friends[0].isHungry = true
// here i expect variable peopleAtBlock2 doesn't changed
// because i just change the peopleAtBlock1 only
assertFalse(peopleAtBlock1[0] == peopleAtBlock2[0])
}
when i run the test it fails because the peopleAtBlock2
changed unexpectedly caused by this code
peopleAtBlock1[0].friends[0].isHungry = true
i want to keep value of peopleAtBlock2
is not changed, how do i do that?
thanks
EDIT:
i have follow answer here using
fun Array<BooleanArray>.copy() = map { it.clone() }.toTypedArray()
converted to my case, the function would be
fun ArrayList<Person>.copy2() = map { it.copy() }.toTypedArray()
but still doesn't work
please check my repl for running in cloud if you dont have kotlin
Upvotes: 1
Views: 383
Reputation: 9692
fun Person.deepCopy(): Person = copy(friends = friends.map { it.deepCopy() })
val peopleAtBlock2 = peopleAtBlock1.map { it.deepCopy() }
Upvotes: 0
Reputation: 8345
In your case peopleAtBlock2
is a shallow copy of peopleAtBlock1
, which means they reference the same objects. so when you change value of an object in peopleAtBlock1
, its reflected in peopleAtBlock2
also.
In order to solve this you will have to create a deep copy of peopleAtBlock1. recommended way to do this is to use serialization. that is first you serialize the original data and then create a copy by de serializing.
there are better ways of doing this but a quick and easy way is to use JSON serialization, which can be done by following the below steps
First add dependency for Gson in your project as
implementation 'com.google.code.gson:gson:2.8.8'
Now move Person
class outside the function, Gson
doesn't work with local classes
Finally you can create a deep copy as
val type = object : TypeToken<ArrayList<Person>>(){}.type
val json = Gson().toJson(peopleAtBlock1, type)
val peopleAtBlock2 = Gson().fromJson<ArrayList<Person>>(json, type)
Upvotes: 1