2

So, I've a Data class Cars. When I first start activity, I'd create a list and add few objects:

val listA: ArrayList<Cars> = ArrayList()
listA.add(*API response objects*)

Everything is good till the moment I decide to create different list and add this list content (basically do a copy):

val listB: ArrayList<Cars> = ArrayList()
listB.addAll(listA)

Then I decide to do some removal commands like:

if (imFeelingLucky) listB.removeAt(position)

Problem: Changes made to listB also take affect on listA (when I delete items from listA it automatically deletes items from listB). What am I missing? Why is this happening? I'm trying to change "content" of the list, not change "objects". How to avoid this?


CODE:

I've two dimensional list - list of cars and inside I've car colors.

Original list (I want to copy elements and not affect this one): listA

List<Cars>:
 Car#1:
      *name_of_car
      *car_colors: List<CarColors> ...
 Car#2:
      *name_of_car
      *car_colors: List<CarColors> ...
 Car#3:
      *name_of_car
      *car_colors: List<CarColors> ...

listC - contains colors for cars. Basically for for-loop.

class testA {

    val listA: ArrayList<Cars> = ArrayList()

    init {
        getData()
        changeData()
    }

    private fun getData() {
        listA.add(..getting data and population listA)
    }

    private fun changeData(): List<Cars> {
        val listB: List<Cars> = ArrayList()
        listB.addAll(listA)

        for (carPosition in listC.size - 1 downTo 0) {
            for (carColorPosition in listC[carPosition].size - 1 downTo 0) {
                if (!listC[carPosition][carColorPosition]) {
                    listB[carPosition].options.removeAt(carColorPosition)
                }
            }
        }

        for (itemToRemovePosition in listB.size - 1 downTo 0) {
            if (listB[itemToRemovePosition] == 0) {
                listB.removeAt(itemToRemovePosition)
            }
        }

        return listB
    }

}
MaaAn13
  • 264
  • 5
  • 24
  • 54
  • 2
    This should not be happening with the code you've shown. Please provide a single continuous block of code that reproduces this issue - for now, it just seems like you're accidentally manipulating both of your lists from somewhere else, which we can't possibly see above. – zsmb13 Apr 03 '18 at 08:06
  • @zsmb13 Updated with code and additional information. – MaaAn13 Apr 03 '18 at 08:27
  • 2
    `listB[carPosition].options.removeAt(carColorPosition)` -- here you remove an item from an inner list. You didn't copy this list. – Marko Topolnik Apr 03 '18 at 08:33
  • @MarkoTopolnik Yes, but why does a change to "object" in `listB` also affects `listA`? If I change object, then it changes everywhere (?) - did not know that. How would u suggest to do elegant copy of inner/outter list. – MaaAn13 Apr 03 '18 at 08:37
  • @PeteWonder When you added all, it just added the same objects to two lists, what you need to do is a deep copy where you clone the individual objects and add them to the list. – jt-gilkeson Apr 03 '18 at 08:38
  • @jt-gilkeson I see. Is there some way to do deep copy in elegant way? I read that `copy()` method in Kotlin does not do a deep copy. – MaaAn13 Apr 03 '18 at 08:41
  • These might be what you are looking for? https://stackoverflow.com/questions/46846025/how-to-clone-or-copy-a-list-in-kotlin https://stackoverflow.com/questions/47359496/kotlin-data-class-copy-method-not-deep-copying-all-members – jt-gilkeson Apr 03 '18 at 08:42
  • @jt-gilkeson `val listB = listA.toMutableList()` does not do a hard-copy in my case (affects both lists) – MaaAn13 Apr 03 '18 at 08:48

1 Answers1

3
val listB: List<Cars> = ArrayList()
listB.addAll(listA)

Does a shallow copy where the same Cars objects are in both lists. What you need is a deep copy:

How to clone or copy a list in kotlin

or

Kotlin data class copy method not deep copying all members

If worst comes to worst you can iterate through the list and add new objects: i.e for (cars in listA) listB.add(Cars(cars.name, cars.options.toMutableList()) or something similar, the important point here is that for every object in all the lists, you need to make a copy of it and re-create the list or use some built-in method to do that if available.

jt-gilkeson
  • 2,661
  • 1
  • 30
  • 40