62

I need to make a copy of a fairly large 2 dimensional array for a project I am working on. I have two 2D arrays:

int[][]current;
int[][]old;

I also have two methods to do the copying. I need to copy the array because current is regularly being updated.

public void old(){
  old=current
}

and

public void keepold(){
  current=old
}

However, this does not work. If I were to call old, make an update on current, and then call keepold, current is not equal to what it was originally. Why would this be?

Thanks

badcoder
  • 3,624
  • 5
  • 32
  • 33
  • 1
    When you find yourself needing to copy multi-dimensional arrays, you may find it's time to consider creating a new class to better manage this data. – corsiKa Apr 11 '11 at 05:25
  • Do you know how to copy a one dimensional array in Java? – jmg Apr 11 '11 at 06:23
  • 1
    http://blog.stackoverflow.com/2010/08/the-death-of-meta-tags/ One can declare a question as a homework question. But tags are for classification and "homework" is not a good classifier, IMO – Louis Rhys Apr 12 '11 at 15:11

13 Answers13

72

Since Java 8, using the streams API:

int[][] copy = Arrays.stream(matrix).map(int[]::clone).toArray(int[][]::new);
Gayan Weerakutti
  • 11,904
  • 2
  • 71
  • 68
48

current=old or old=current makes the two array refer to the same thing, so if you subsequently modify current, old will be modified too. To copy the content of an array to another array, use the for loop

for(int i=0; i<old.length; i++)
  for(int j=0; j<old[i].length; j++)
    old[i][j]=current[i][j];

PS: For a one-dimensional array, you can avoid creating your own for loop by using Arrays.copyOf

Sébastien
  • 11,860
  • 11
  • 58
  • 78
Louis Rhys
  • 34,517
  • 56
  • 153
  • 221
26
/**
 * Clones the provided array
 * 
 * @param src
 * @return a new clone of the provided array
 */
public static int[][] cloneArray(int[][] src) {
    int length = src.length;
    int[][] target = new int[length][src[0].length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(src[i], 0, target[i], 0, src[i].length);
    }
    return target;
}

Is it possible to modify this code to support n-dimensional arrays of Objects?

You would need to support arbitrary lengths of arrays and check if the src and destination have the same dimensions, and you would also need to copy each element of each array recursively, in case the Object was also an array.

It's been a while since I posted this, but I found a nice example of one way to create an n-dimensional array class. The class takes zero or more integers in the constructor, specifying the respective size of each dimension. The class uses an underlying flat array Object[] and calculates the index of each element using the dimensions and an array of multipliers. (This is how arrays are done in the C programming language.)

Copying an instance of NDimensionalArray would be as easy as copying any other 2D array, though you need to assert that each NDimensionalArray object has equal dimensions. This is probably the easiest way to do it, since there is no recursion, and this makes representation and access much simpler.

Community
  • 1
  • 1
mbomb007
  • 3,788
  • 3
  • 39
  • 68
12

I solved it writing a simple function to copy multidimensional int arrays using System.arraycopy

public static void arrayCopy(int[][] aSource, int[][] aDestination) {
    for (int i = 0; i < aSource.length; i++) {
        System.arraycopy(aSource[i], 0, aDestination[i], 0, aSource[i].length);
    }
}

or actually I improved it for for my use case:

/**
 * Clones the provided array
 * 
 * @param src
 * @return a new clone of the provided array
 */
public static int[][] cloneArray(int[][] src) {
    int length = src.length;
    int[][] target = new int[length][src[0].length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(src[i], 0, target[i], 0, src[i].length);
    }
    return target;
}
Daniel Backman
  • 5,121
  • 1
  • 32
  • 37
6

You can also do as follows:

public static int[][] copy(int[][] src) {
    int[][] dst = new int[src.length][];
    for (int i = 0; i < src.length; i++) {
        dst[i] = Arrays.copyOf(src[i], src[i].length);
    }
    return dst;
}
Johnny Lim
  • 5,623
  • 8
  • 38
  • 53
2

Using java 8 this can be done with

int[][] destination=Arrays.stream(source)
                    .map(a ->  Arrays.copyOf(a, a.length))
                    .toArray(int[][]::new);
Winter
  • 3,894
  • 7
  • 24
  • 56
Rakesh Chauhan
  • 413
  • 4
  • 7
1

Arrays in java are objects, and all objects are passed by reference. In order to really "copy" an array, instead of creating another name for an array, you have to go and create a new array and copy over all the values. Note that System.arrayCopy will copy 1-dimensional arrays fully, but NOT 2-dimensional arrays. The reason is that a 2D array is in fact a 1D array of 1D arrays, and arrayCopy copies over pointers to the same internal 1D arrays.

Sajid
  • 4,381
  • 20
  • 14
  • 1
    Arrays are not objects. Array variables are references, similar to how object variables are references, but they are not objects. – Andrew Case Oct 15 '14 at 17:39
  • Arrays are objects. Java Language Specification Chapter 10.. *In the Java programming language, arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2). All methods of class Object may be invoked on an array.* https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#:~:text=In%20the%20Java%20programming%20language,be%20invoked%20on%20an%20array. – aran Mar 03 '21 at 02:52
0

I am using this function:

public static int[][] copy(final int[][] array) {
    if (array != null) {
        final int[][] copy = new int[array.length][];

        for (int i = 0; i < array.length; i++) {
            final int[] row = array[i];

            copy[i] = new int[row.length];
            System.arraycopy(row, 0, copy[i], 0, row.length);
        }

        return copy;
    }

    return null;
}

The big advantage of this approach is that it can also copy arrays that don't have the same row count such as:

final int[][] array = new int[][] { { 5, 3, 6 }, { 1 } };
Niklas
  • 23,674
  • 33
  • 131
  • 170
0

Here's how you can do it by using loops.

public static int[][] makeCopy(int[][] array){
    b=new int[array.length][];

    for(int row=0; row<array.length; ++row){
        b[row]=new int[array[row].length];
        for(int col=0; col<b[row].length; ++col){
            b[row][col]=array[row][col];
        }
    }
    return b;
}
  • Take care, this is dimensions slower than solutions based on System.arraycopy. System.arraycopy is implemented natively based on the underlying hardware platform. – Michael Apr 23 '23 at 16:39
0
current = old ;

Assignment operations doesnot copy elements of one array to another. You are just making the current matrix refer to the old matrix. You need to do a member wise copy.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
0

you could also use a for each loop

int r=0;
for(int[] array:old){
    int c=0;
    for(int element:array)
        current[r][c++]=array;
    r++;
}

Or

int c=0;
for(int array[]:old){
    System.arraycopy(array,0,current[c++],0,array.length);
}

However something like:

int c=0;
for(int[] array:old){
    current[c++]=array;
}

would be wrong as it would just copy references of the subarrays of old and changes made to old would be reflected in current.

Omnicacorp
  • 41
  • 7
-2
public  static byte[][] arrayCopy(byte[][] arr){
    if(arr!=null){
        int[][] arrCopy = new int[arr.length][] ;
        System.arraycopy(arr, 0, arrCopy, 0, arr.length);
        return arrCopy;
    }else { return new int[][]{};}
}
Satish
  • 127
  • 1
  • 1
  • 7
-8

You can give below code a try,

public void multiArrayCopy(int[][] source,int[][] destination){
destination=source.clone();}

Hope it works.

Adil Bhatty
  • 17,190
  • 34
  • 81
  • 118
  • 7
    No, this won't work. Because assigning to the local variable `destination` has no effect after `multiArrayCopy` at all. – jmg Apr 11 '11 at 06:22