본문 바로가기
2023년 이전/kotlin

ArrayList copy 관련

by JeongUPark 2019. 10. 25.
반응형

매우 간단한 거지만 어디에 적어놓지 않고 쓸 때마다 확인하려고 하니 안 좋은 방법인것 같아서 직접 글을 쓰기로 했습니다. ArrayList 사용 시 다음과 같이 사용할 경우 원본 데이터에 영향을 줄 수 있습니다.

 

fun main(){
    val kk = ArrayList<Test_Obj>()
    kk.add(Test_Obj("1","a"))
    kk.add(Test_Obj("2","b"))
    kk.add(Test_Obj("3","c"))
    kk.add(Test_Obj("4","d"))

    val g= kk

    g.add(Test_Obj("5","e"))


    for (i in kk.indices) {
        println("id : ${kk[i].id} | data : ${kk[i].data} ")
    }
}
class Test_Obj(input_id: String, input_data : String) {
    var id = "0"
    var data = "z"
    init {
        this.id = input_id
        this.data = input_data
    }

    fun setid(input_id: String,input_data : String) {
        id = input_id
        data = input_data
    }
}

 

이 처럼 1,2,3,4나와야 하는데, 5까지 결과가 나와버렸습니다. 그이유는 디버깅을 해보면

이렇게 두개의 메모리 주소가 같은 것을 볼 수 있습니다. 즉,  ArrayList 자체를 복사한다는 의미로  컴퓨터 입장에서는 똑같은 ArrayList로 볼 수 있습니다. 그럼 clone과 직접 복사의 경우를 확인해 보겠습니다.

 val g = kk.clone() as ArrayList<Test_Obj>
 
 // or
 val g = ArrayList<Test_obj>()
  for (i in kk) {
        g.add(i)
    }

clone의 경우나 직접복사의 경우나 둘다 ArrayList의 메모리 값이 다른 것을 확인 할 수있습니다.

그렇기 때문에 ArrayList g에 add 할 경우에는 ArrayList kk에 영향을 주지 않습니다. 하지만 내부 데이터의 메모리 값을 보면 

이렇게 동일한 것을 볼 수 있습니다. 즉 ArrayList g의 객체(Test_Obj)들 중 하나의 데이터를 변경 할 경우 ArrayList kk에 있는 동일한 객체도 변경됩니다. 확인해 보겠습니다.

fun main(){
    val kk = ArrayList<Test_Obj>()
    kk.add(Test_Obj("1","a"))
    kk.add(Test_Obj("2","b"))
    kk.add(Test_Obj("3","c"))
    kk.add(Test_Obj("4","d"))

    val g = kk.clone() as ArrayList<Test_Obj>

    g.add(Test_Obj("5","e"))
    g[3].id = "8"
    g[3].data = "h"

    for (i in kk.indices) {
        println("id : ${kk[i].id} | data : ${kk[i].data} ")
    }
}
}
class Test_Obj(input_id: String, input_data : String) {
    var id = "0"
    var data = "z"
    init {
        this.id = input_id
        this.data = input_data
    }

    fun setid(input_id: String,input_data : String) {
        id = input_id
        data = input_data
    }
}

이렇게 하면 아래와 같은 결과가 나옵니다.

즉, 데이터 변경시 원본 데이터에도 영향을 주기 됩니다. 그렇기 때문에 정말 새로운 ArrayList에 데이터를 복사를 하고 싶으실 경우에는 clone 을 쓰지않고 직접 복사를 해주는데 그때 다음과 같이 만들어 줍니다.

fun main(){
    val kk = ArrayList<Test_Obj>()
    kk.add(Test_Obj("1","a"))
    kk.add(Test_Obj("2","b"))
    kk.add(Test_Obj("3","c"))
    kk.add(Test_Obj("4","d"))

    val g = ArrayList<Test_Obj>()
    for (i in kk) {
        val  t = Test_Obj(i.id,i.data)
        g.add(t)
    }
    g.add(Test_Obj("5","e"))
    g[3].id = "8"
    g[3].data = "h"

    for (i in kk.indices) {
        println("id : ${kk[i].id} | data : ${kk[i].data} ")
    }
}
class Test_Obj(input_id: String, input_data : String) {
    var id = "0"
    var data = "z"
    init {
        this.id = input_id
        this.data = input_data
    }

    fun setid(input_id: String,input_data : String) {
        id = input_id
        data = input_data
    }
}

그 결과를 보면

각 객체마다 메모리 값이 다름을 확인 할 수 있고, 데이터는 동일함을 확인 할 수 있습니다.(단 g[3]의 데이터는 8과 h로 변경됩니다.)

결과는 

입니다.

 

위의 내용처럼 동일한 데이터를 가진 신규 ArrayList를 만들기 위해서는 ArrayList도 각각의 객체도 전부 신규로 해서 적용해야 합니다. (Java도 동일 합니다.)

반응형