How to deep copy an irregular 2D array
How can I deep copy an irregularly shaped 2D array in Java?
Ie.
int[][] nums = {{5},
{9,4},
{1,7,8},
{8,3,2,10}}
I'm unable to use Arrays.arrayCopy()
for some reason (versioning?)
Solution 1:
int[][] copy = new int[nums.length][];
for (int i = 0; i < nums.length; i++) {
copy[i] = new int[nums[i].length];
for (int j = 0; j < nums[i].length; j++) {
copy[i][j] = nums[i][j];
}
}
You can replace the second loop with System.arraycopy() or Arrays.copyOf().
Solution 2:
I wrote this in Eclipse, tested it, came back and found that João had beaten me to almost exactly the same solution. I upvoted him, but here's mine for comparison. I guess it's instructive to see the very slight details people choose to do differently.
private static int[][] copy2d(int[][] nums) {
int[][] copy = new int[nums.length][];
for (int i = 0; i < copy.length; i++) {
int[] member = new int[nums[i].length];
System.arraycopy(nums[i], 0, member, 0, nums[i].length);
copy[i] = member;
}
return copy;
}
For extra credit, try writing one that copies an n-dimensional array where n is arbitrary.
Solution 3:
N-dimensional deep copy
public class ArrayTest extends TestCase {
public void testArrays() {
Object arr = new int[][]{
{5},
{9, 4},
{1, 7, 8},
{8, 3, 2, 10}
};
Object arrCopy = copyNd(arr);
int height = Array.getLength(arr);
for (int r = 0; r < height; r++) {
Object rowOrigonal = Array.get(arr, r);
Object rowCopy = Array.get(arrCopy, r);
int width = Array.getLength(rowOrigonal);
for (int c = 0; c < width; c++) {
assertTrue(rowOrigonal.getClass().isArray());
assertTrue(rowCopy.getClass().isArray());
assertEquals(Array.get(rowOrigonal, c), Array.get(rowCopy, c));
System.out.println(Array.get(rowOrigonal, c) + ":" + Array.get(rowCopy, c));
}
}
}
public static Object copyNd(Object arr) {
if (arr.getClass().isArray()) {
int innerArrayLength = Array.getLength(arr);
Class component = arr.getClass().getComponentType();
Object newInnerArray = Array.newInstance(component, innerArrayLength);
//copy each elem of the array
for (int i = 0; i < innerArrayLength; i++) {
Object elem = copyNd(Array.get(arr, i));
Array.set(newInnerArray, i, elem);
}
return newInnerArray;
} else {
return arr;//cant deep copy an opac object??
}
}
}
Solution 4:
Some folks suggest clone()
-- just to be extra clear, clone()
on a multi-dimensional array is only a shallow clone. original.clone()[0] == original[0]
. But (for primitives) you can use clone()
instead of System.arraycopy()
once you're down to one-dimensional arrays.
Solution 5:
Here's one that specializes to deeply cloning int[][]
. It also allows any of the int[]
to be null
.
import java.util.*;
public class ArrayDeepCopy {
static int[][] clone(int[][] arr) {
final int L = arr.length;
int[][] clone = new int[L][];
for (int i = 0; i < clone.length; i++) {
clone[i] = (arr[i] == null) ? null : arr[i].clone();
}
return clone;
}
public static void main(String[] args) {
int[][] a = {
{ 1, },
{ 2, 3, },
null,
};
int[][] b = a.clone();
System.out.println(a[0] == b[0]); // "true", meaning shallow as expected!
b = clone(a); // this is deep clone!
System.out.println(Arrays.deepEquals(a, b)); // "true"
System.out.println(a[0] == b[0]); // "false", no longer shallow!
}
}