66

i have a 2d array called matrix of type int that i want to copy to a local variable in a method so i can edit it

whats the best way to copy the array, i am having some troubles

for example

    int [][] myInt;
    for(int i = 0; i< matrix.length; i++){
        for (int j = 0; j < matrix[i].length; j++){
            myInt[i][j] = matrix[i][j];
        }
    }

    //do some stuff here
    return true;
}
roberto duran
  • 661
  • 1
  • 5
  • 3

5 Answers5

103

There are two good ways to copy array is to use clone and System.arraycopy().

Here is how to use clone for 2D case:

int [][] myInt = new int[matrix.length][];
for(int i = 0; i < matrix.length; i++)
    myInt[i] = matrix[i].clone();

For System.arraycopy(), you use:

int [][] myInt = new int[matrix.length][];
for(int i = 0; i < matrix.length; i++)
{
  int[] aMatrix = matrix[i];
  int   aLength = aMatrix.length;
  myInt[i] = new int[aLength];
  System.arraycopy(aMatrix, 0, myInt[i], 0, aLength);
}

I don't have a benchmark but I can bet with my 2 cents that they are faster and less mistake-prone than doing it yourself. Especially, System.arraycopy() as it is implemented in native code.

starball
  • 20,030
  • 7
  • 43
  • 238
NawaMan
  • 25,129
  • 10
  • 51
  • 77
  • 7
    Arrays.copyOf() also can be used – Pete Kirkham Nov 06 '09 at 10:40
  • 3
    Pete is right. But Arrays.copyOf() makes use of System.arraycopy() with an over head for the assumption that the length of the result might not be the same as the original. In this case we know for sure the size of the result, so it is much more efficient to use clone() and System.arraycopy() as they are native. Nonetheless, Arrays.copyOf() can be use too. – NawaMan Nov 06 '09 at 11:05
  • 2
    @PeteKirkham Arrays.copyOf() does not deep copy a 2d matrix. It just refers same 2nd dimension arrays. – Sachin Verma Feb 26 '18 at 12:27
  • 1
    @SachinVerma yes. Rather than doing the new and then arraycopy in the second example, you make one library call that does both. – Pete Kirkham Feb 26 '18 at 13:58
21

It is possible to use streams in Java 8 to copy a 2D array.

@Test
public void testCopy2DArray() {
   int[][] data = {{1, 2}, {3, 4}};
   int[][] dataCopy = Arrays.stream(data)
             .map((int[] row) -> row.clone())
             .toArray((int length) -> new int[length][]);

   assertNotSame(data, dataCopy);
   assertNotSame(data[0], dataCopy[0]);
   assertNotSame(data[1], dataCopy[1]);

   dataCopy[0][1] = 5;
   assertEquals(2, data[0][1]);
   assertEquals(5, dataCopy[0][1]);
}
NickF
  • 469
  • 4
  • 7
  • 17
    For one-liner - collapse all lambdas to method references `Arrays.stream(data).map(int[]::clone).toArray(int[][]::new);` But please note that for huge arrays native System.arraycopy should be (probably?) faster, unless you `parallel()` your stream. – NIA Oct 03 '16 at 11:55
  • 2
    @NIA `clone()` is essentially identical to `System.arraycopy()` in speed on the oracle jvm: both are native methods . Your code is the best i've seen in all of the answers and comments. – WestCoastProjects Mar 06 '21 at 19:49
7

You are not initializing the local 2D array.

int[][] myInt = new int[matrix.length][];
for(int i = 0; i < matrix.length; i++)
{
  myInt[i] = new int[matrix[i].length];
  for (int j = 0; j < matrix[i].length; j++)
  {
    myInt[i][j] = matrix[i][j];
  }
}
Amarghosh
  • 58,710
  • 11
  • 92
  • 121
1

If the data is large you should consider using a proper linear algebra library like colt or nd4j. System.arraycopy will likely only be meaningfully faster if the array were single dimensional. Otherwise it can not copy the entire data as one unit and then reshape it as in numpy or R.

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560
-15

you can code like this also myInt = matrix.clone();

valli
  • 5,797
  • 2
  • 19
  • 9