Why does Array.copyOf() mutate the original array in case of 2D Arrays?

江枫思渺然 提交于 2021-02-05 08:09:16

问题


If I create a 2D int array in Java, and then make a copy of it using Arrays.copyOf(), like so -

jshell> int[][] c1 = {{1,2}, {3,4}}
c1 ==> int[2][] { int[2] { 1, 2 }, int[2] { 3, 4 } }

jshell> int[][] d1 = Arrays.copyOf(c1, c1.length)
d1 ==> int[2][] { int[2] { 1, 2 }, int[2] { 3, 4 } }

If I then change an element in the copy, why does the corresponding cell in the original 2D array get mutated in the process?

jshell> d1[0][0] = 0
$21 ==> 0

jshell> d1
d1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } }

jshell> c1
c1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } } // c1[0][0] was 1 originally

This leads me to believe that during a copy of 2D arrays using Arrays.copyOf(), a separate copy is created only for the outermost array, while each inner array is still a reference to the inner arrays of the original 2D array?

jshell> d1 = null
d1 ==> null

jshell> c1
c1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } }

If so, why is it this way? Shouldn't Arrays.copyOf() create distinct copies, at least per the docs? Is this behavior documented anywhere in the Oracle docs?

Lastly, what is the correct way to create distinct copies of a 2D array, the same way Arrays.copyOf() works for 1D arrays?


回答1:


A 2D array is basically an array that contains arrays, and Arrays.copyOf does a shallow copy, so only the outer array (the array of arrays) is copied, not the values inside the array (in this case, arrays of int, ie int[]). As a result, both the original and the copy contain the same int[] arrays, so if you modify through one, the result is also visible through the other.

This is explicitly mentioned in the javadoc:

For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.

You do need to read that with the knowledge of the signature: <T> T[] copyOf(T[], int). The array copied is T[] (an array of T, where T is int[]), not T[][]!

For a deep copy of a 2D array, you will have to deep copy the array yourself, for example see How do I do a deep copy of a 2d array in Java?




回答2:


Method Arrays.copyOf does not perform a deep copy of an array, nor does System.arraycopy method. You should implement the algorithm of deep copy of the array yourself with the required copy depth. For example:

int[][] arr1 = {{1, 2}, {3, 4}};                 // original array
int[][] arr2 = Arrays.copyOf(arr1, arr1.length); // shallow copy
int[][] arr3 = Arrays.stream(arr1)               // deep copy
        .map(Arrays::stream)
        .map(IntStream::toArray)
        .toArray(int[][]::new);

arr1[0][0] = 7;

System.out.println(Arrays.deepToString(arr1)); // [[7, 2], [3, 4]]
System.out.println(Arrays.deepToString(arr2)); // [[7, 2], [3, 4]]
System.out.println(Arrays.deepToString(arr3)); // [[1, 2], [3, 4]]

And the same is true for an array of objects:

public class Test {
    public static void main(String[] args) {
        SomeObject[] arr1 = {                                 // original array
                new SomeObject(1),
                new SomeObject(2),
                new SomeObject(3),
                new SomeObject(4)};
        SomeObject[] arr2 = Arrays.copyOf(arr1, arr1.length); // shallow copy
        SomeObject[] arr3 = Arrays.stream(arr1)               // deep copy
                .mapToInt(SomeObject::getField)
                .mapToObj(SomeObject::new)
                .toArray(SomeObject[]::new);

        arr1[0].setField(7);

        System.out.println(Arrays.toString(arr1)); // [7, 2, 3, 4]
        System.out.println(Arrays.toString(arr2)); // [7, 2, 3, 4]
        System.out.println(Arrays.toString(arr3)); // [1, 2, 3, 4]
    }

    static class SomeObject {
        int field;

        public SomeObject(int field) { this.field = field; }

        public int getField() { return field; }

        public void setField(int field) { this.field = field; }

        public String toString() { return String.valueOf(field); }
    }
}


来源:https://stackoverflow.com/questions/65519193/why-does-array-copyof-mutate-the-original-array-in-case-of-2d-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!