How do I do a deep copy of a 2d array in Java?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


How do I do a deep copy of a 2d array in Java?



I just got bit by using .clone() on my 2d boolean array, thinking that this was a deep copy.


.clone()


boolean



How can I perform a deep copy of my boolean array?


boolean



Should I loop through it and do a series of System.arraycopy's?


System.arraycopy




6 Answers
6



Yes, you should iterate over 2D boolean array in order to deep copy it. Also look at java.util.Arrays#copyOf methods if you are on Java 6.


java.util.Arrays#copyOf



I would suggest the next code for Java 6:


public static boolean deepCopy(boolean original) {
if (original == null) {
return null;
}

final boolean result = new boolean[original.length];
for (int i = 0; i < original.length; i++) {
result[i] = Arrays.copyOf(original[i], original[i].length);
// For Java versions prior to Java 6 use the next:
// System.arraycopy(original[i], 0, result[i], 0, original[i].length);
}
return result;
}





Note that this does not seem to work for Objects. See stackoverflow.com/questions/15135104/…
– Timo
Jan 12 '15 at 11:55




Objects



I'm a fan of the Arrays utility. It has a copyOf method that will do a deep copy of a 1-D array for you, so you'd want something like this:


//say you have boolean foo;
boolean nv = new boolean[foo.length][foo[0].length];
for (int i = 0; i < nv.length; i++)
nv[i] = Arrays.copyOf(foo[i], foo[i].length);





Note, that this only creates a "deep copy" for primitive types! Arrays.copyOf() itself only creates shallow copies.
– codepleb
Jun 19 '15 at 15:53



I've managed to come up with a recursive array deep copy. It seems to work pretty well even for multi dimensional arrays with varying dimension lengths e.g.


private static final int INT_3D_ARRAY = {
{
{1}
},
{
{2, 3},
{4, 5}
},
{
{6, 7, 8},
{9, 10, 11},
{12, 13, 14}
}
};



Here is the utility method.


@SuppressWarnings("unchecked")
public static <T> T deepCopyOf(T array) {

if (0 >= array.length) return array;

return (T) deepCopyOf(
array,
Array.newInstance(array[0].getClass(), array.length),
0);
}

private static Object deepCopyOf(Object array, Object copiedArray, int index) {

if (index >= Array.getLength(array)) return copiedArray;

Object element = Array.get(array, index);

if (element.getClass().isArray()) {

Array.set(copiedArray, index, deepCopyOf(
element,
Array.newInstance(
element.getClass().getComponentType(),
Array.getLength(element)),
0));

} else {

Array.set(copiedArray, index, element);
}

return deepCopyOf(array, copiedArray, ++index);
}



EDIT: Updated the code to work with primitive arrays.





This looks good. What does Array refer to?
– elgehelge
Apr 7 '14 at 6:00




Array





Edit: Found out myself: import java.lang.reflect.Array;
– elgehelge
Apr 7 '14 at 6:09


import java.lang.reflect.Array;



Yes, that's the only way to do it. Neither java.util.Arrays not commons-lang offer deep copy for arrays.


java.util.Arrays



In Java 8 this can be accomplished as a one-liner using lambdas:


<T> T deepCopy(T matrix) {
return java.util.Arrays.stream(matrix).map(el -> el.clone()).toArray($ -> matrix.clone());
}





Using clone() is rarely a good idea.
– Ypnypn
Nov 5 '15 at 1:00


clone()





@Ypnypn I totally agree, except for arrays. Using clone() is generally the fastest and simplest way to copy an array.
– SlavaSt
Nov 5 '15 at 12:35




clone()





clone() for arrays is totally fine.
– Christian Hujer
Nov 8 '15 at 3:51


clone()





Nice, but I don't like the last part, which initializes the returned array with a clone of the matrix. I prefer the simpler java.util.Arrays.stream(matrix).map(el -> el.clone()).toArray(T::new);
– Jocelyn LECOMTE
Nov 7 '16 at 8:24




java.util.Arrays.stream(matrix).map(el -> el.clone()).toArray(T::new);





Also, consider the code here: stackoverflow.com/a/8200027/109941
– Jim G.
Apr 5 at 14:46



Here's a reflective example using java.lang.reflect.Array which is more robust and a bit easier to follow. This method will copy any array, and deeply copies multidimensional arrays.


java.lang.reflect.Array


package mcve.util;

import java.lang.reflect.*;

public final class Tools {
private Tools() {}
/**
* Returns a copy of the specified array object, deeply copying
* multidimensional arrays. If the specified object is null, the
* return value is null. Note: if the array object has an element
* type which is a reference type that is not an array type, the
* elements themselves are not deep copied. This method only copies
* array objects.
*
* @param array the array object to deep copy
* @param <T> the type of the array to deep copy
* @return a copy of the specified array object, deeply copying
* multidimensional arrays, or null if the object is null
* @throws IllegalArgumentException if the specified object is not
* an array
*/
public static <T> T deepArrayCopy(T array) {
if (array == null)
return null;

Class<?> arrayType = array.getClass();
if (!arrayType.isArray())
throw new IllegalArgumentException(arrayType.toString());

int length = Array.getLength(array);
Class<?> componentType = arrayType.getComponentType();

@SuppressWarnings("unchecked")
T copy = (T) Array.newInstance(componentType, length);

if (componentType.isArray()) {
for (int i = 0; i < length; ++i)
Array.set(copy, i, deepArrayCopy(Array.get(array, i)));
} else {
System.arraycopy(array, 0, copy, 0, length);
}

return copy;
}
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

Visual Studio Code: How to configure includePath for better IntelliSense results