[Kotlin] array copyOf, clone

2022. 10. 4. 16:56·JVM/Kotlin

 

1차원 배열 복사

copyOf() 메소드를 사용하면 deep copy 가 된다.

새로운 레퍼런스 주소로 별도 공간에 array 가 할당된다.

copyOf 로 deep copy 하면
복사된 배열의 값을 수정해도 원본 배열에는 영향을 미치지 않는다.

1차원 배열 복사 Test

// 1차원 배열 copy
@Test
internal fun firstArray() {
    val nums = intArrayOf(1, 3, 5, 7, 9)
    val copiedArr = nums.copyOf()
    // copy 된 배열 값 수정
    copiedArr[0] = 0


    println("Original Array")
    for (num in nums) print("$num ")

    println()
    println("==================")


    println("Copied Array")
    for (num in copiedArr) print("$num ")
}

 

결과

 

 

copyOf with New Size

copyOf() 의 인자로 복사본의 크기를 넘길 수 있는데

기존 배열보다 적은 수로 지정하면 짤림이 일어나고 더 크게 설정하면 Falsy (null, 0, false) 등의 값으로 padding 된다.

@Test
internal fun testNewSizeArray() {
    val nums = intArrayOf(1, 3, 5, 7, 9)
    // if newSize is greater than original one, padding value is to be falsy one (null, false, 0).
    println("Over sized array")
    val overSizedCopyArr = nums.copyOf(10)
    for (num in overSizedCopyArr) print("$num ")

    println()
    println("Truncated array")
    // if newSize is less than original one, copy array is truncated
    val truncatedCopyArr = nums.copyOf(3)
    for (num in truncatedCopyArr) print("$num ")

	// [Result]
    // Over-sized array
    // 1 3 5 7 9 0 0 0 0 0 
    // Truncated array
    // 1 3 5 
}

 

Clone 메소드를 통한 복사

copyOf 와 마찬가지로 Deep Copy 가 일어나기 때문에 복사본을 수정해도 원본에 영향을 미치지 않는다.

 

@Test
internal fun testClone() {
    val nums = intArrayOf(1, 3, 5, 7, 9)
    val clonedArr = nums.clone()
    clonedArr[0] = 0

    println("======Original Array=====")
    for (num in nums) print("$num ")
    println()

    println("======Copied Array=====")
    for (num in clonedArr) print("$num ")

    // [Result]
    // ======Original Array=====
    //1 3 5 7 9 
    //======Copied Array=====
    //0 3 5 7 9
}

 

copyOfRange() 

지정한 범위 내에서 copy할 때 사용한다.

java, kotlin 진영에서의 range 는 보통 [시작 인덱스, 종료 인덱스) 로 종료 인덱스는 작업 대상에 포함시키지 않는다.

@Test
internal fun testCopyOfRange() {
    val nums = intArrayOf(1, 3, 5, 7, 9)

    // [start index, end index)
    val rangeCopiedArr = nums.copyOfRange(1, 3)

    rangeCopiedArr.forEach { print("$it ") }

    // [Result]
    // 3 5
}

 

 


⚠️ 2차원 배열 복사 주의

 

@Test
internal fun testSecondArray() {
    val secondArrays = arrayOf(
        intArrayOf(1, 3, 5, 7, 9),
        intArrayOf(2, 4, 6, 8, 10),
        intArrayOf(0, -13, -15, 100, 15)
    )

    val copiedArray = secondArrays.copyOf()
    copiedArray[0][0] = 0

    println("Original Array!")
    for (arr in secondArrays) {
        for (num in arr) print("$num ")
        println()
    }
    
    println("======================")
    
    println("Copied Array!")
    for (arr in copiedArray) {
        for (num in arr) print("$num ")
        println()
    }

}

 

결과

 

 

왜 이런 일이 일어나는 걸까?

2차원 배열을 도식화해보자.

2차원 배열의 원소를 arr[row][col] 로 표현했을 때 경우
배열의 size(행 개수) 만큼, 즉, row 에 대한 Deep Copy 만 일어난다.

행 속의 열(col) 은 Deep Copy 의 대상이 아니다.

배열의 각각의 arr[row] 는 arr[row][col1] arr[row][col2] .... arr[row][last col] 의 시작 주소를 가리킨다.

즉, 1차원 배열의 시작주소를 가리키는 arr[row] 의 값만 새로운 레퍼런스로 Deep Copy 가 일어난다.  (JVM 에서는 포인터가 아니라 레퍼런스로 강제되어있다.) 따라서 복사된 레퍼런스로 접근해도 동일한 원본 배열에 접근하게 된다.

 

copyOf 의 원형

@kotlin.internal.InlineOnly
public actual inline fun <T> Array<T>.copyOf(): Array<T> {
// 2차원 배열이 인자로 들어오면, size 는 행의 개수가 된다.
// 열은 Deep Copy 대상이 아니다.
    return java.util.Arrays.copyOf(this, size)
}

 

 

2차원 배열 Deep Copy

물론 모든 원소를 순회하며 복사해도 괜찮지만

한 행씩 복사하는 방법이 있다.

 

@Test
internal fun testDeepCopy2DimensionalArray() {
    val secondArrays = arrayOf(
        intArrayOf(1, 3, 5, 7, 9),
        intArrayOf(2, 4, 6, 8, 10),
        intArrayOf(0, -13, -15, 100, 15)
    )

    // deep copy with for each row
    val copiedArr = Array(secondArrays.size){idx-> secondArrays[idx].copyOf()}
    copiedArr[0][0] = 0

    println("Original Array!")
    for (arr in secondArrays) {
        for (num in arr) print("$num ")
        println()
    }
    println("==============")

    println("Copied Array!")
    for (arr in copiedArr) {
        for (num in arr) print("$num ")
        println()
    }
}

 

결과

저작자표시 (새창열림)

'JVM > Kotlin' 카테고리의 다른 글

[Kotlin] Priority Queue  (0) 2022.10.22
[Kotlin] Array vs ArrayList vs LinkedList vs Queue  (0) 2022.09.18
[Kotlin] data class  (0) 2022.09.18
[Java, Kotlin] equals, HashCode  (0) 2022.09.18
[Kotlin] HashMap, LinkedHashMap, HashSet, LinkedHashSet  (0) 2022.09.17
'JVM/Kotlin' 카테고리의 다른 글
  • [Kotlin] Priority Queue
  • [Kotlin] Array vs ArrayList vs LinkedList vs Queue
  • [Kotlin] data class
  • [Java, Kotlin] equals, HashCode
M_Falcon
M_Falcon
  • M_Falcon
    Falcon
    M_Falcon
  • 전체
    오늘
    어제
    • 분류 전체보기 (429)
      • Web (16)
        • Nodejs (14)
        • Javascript (23)
        • FrontEnd (4)
      • DataBase (39)
        • Fundamental (1)
        • Redis (4)
        • PostgreSQL (10)
        • NoSQL (4)
        • MySQL (9)
        • MSSQL (3)
        • Error (4)
      • Algorithm (79)
        • Algorithm (문제풀이) (56)
        • Algorithm (이론) (23)
      • JVM (64)
        • Spring (13)
        • JPA (5)
        • Kotlin (13)
        • Java (23)
        • Error (7)
      • 기타 (68)
        • Kafka (3)
        • Kubernetes (3)
        • Docker (12)
        • git (19)
        • 잡동사니 (26)
      • 재테크 (11)
        • 세무 (4)
        • 투자 (3)
        • 보험 (0)
      • BlockChain (2)
        • BitCoin (0)
      • C (32)
        • C (10)
        • C++ (17)
        • Error (3)
      • Low Level (8)
        • OS (3)
        • 시스템 보안 (5)
      • 네트워크 (3)
      • LINUX (30)
        • Linux (26)
        • Error (4)
      • 저작권과 스마트폰의 이해 (0)
      • 생각 뭉치 (6)
      • 궁금증 (2)
      • Private (4)
        • 이직 경험 (0)
        • 꿈을 찾아서 (1)
      • Android (21)
        • OS (4)
  • 블로그 메뉴

    • 홈
    • WEB
    • 알고리즘
    • DataBase
    • Linux
    • Mobile
    • C
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    백준
    PostgreSQL
    Bitcoin
    android
    Spring
    ubuntu
    JPA
    Kotlin
    알고리즘
    java
    database
    프로그래머스
    algorithm
    Programmers
    docker
    javascript
    C++
    Git
    kafka
    linux
  • hELLO· Designed By정상우.v4.10.3
M_Falcon
[Kotlin] array copyOf, clone
상단으로

티스토리툴바