¿Cómo hago una copia profunda de una matriz 2D en Java?

Acabo de obtener un poco al usar .clone() en mi matriz boolean 2d, pensando que esta era una copia profunda.

¿Cómo puedo realizar una copia profunda de mi matriz boolean[][] ?

¿Debería recorrerlo y hacer una serie de System.arraycopy ?

Sí, debe iterar sobre una matriz booleana 2D para poder copiarla en profundidad. También mire los métodos java.util.Arrays#copyOf si está en Java 6.

Sugeriría el próximo código para 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; } 

Soy un fanático de la utilidad Arrays. Tiene un método copyOf que hará una copia profunda de una matriz 1-D para ti, por lo que querrías algo como esto:

 //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); 

Me las he arreglado para llegar a una copia profunda de matriz recursiva. Parece funcionar bastante bien incluso para matrices multidimensionales con diferentes longitudes de dimensión, por ejemplo

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

Aquí está el método de utilidad.

 @SuppressWarnings("unchecked") public static  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); } 

EDITAR: actualizó el código para trabajar con matrices primitivas.

Sí, esa es la única forma de hacerlo. Ni java.util.Arrays not commons-lang ofrecen una copia profunda para matrices.

En Java 8, esto se puede lograr como una línea usando lambdas:

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

Aquí hay un ejemplo reflexivo que usa java.lang.reflect.Array que es más robusto y un poco más fácil de seguir. Este método copiará cualquier matriz y copiará profundamente matrices multidimensionales.

 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  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 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; } }