Hoe maak ik een diepe kopie van een 2D-array in Java?

Ik ben zojuist gebeten door .clone()te gebruiken op mijn 2d booleanarray, in de veronderstelling dat dit een diepe kopie was.

Hoe kan ik een diepe kopie maken van mijn boolean[][]array?

Moet ik er doorheen bladeren en een reeks System.arraycopy‘s maken?


Antwoord 1, autoriteit 100%

Ja, u moet de 2D-booleaanse array herhalen om deze diep te kopiëren. Kijk ook naar de java.util.Arrays#copyOfmethoden als je Java 6 gebruikt.

Ik zou de volgende code voor Java 6 willen voorstellen:

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

Antwoord 2, autoriteit 35%

In Java 8 kan dit worden bereikt als een one-liner met behulp van lambdas:

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

Antwoord 3, autoriteit 17%

Ik ben een fan van het hulpprogramma Arrays. Het heeft een copyOf-methode die een diepe kopie van een 1-D-array voor je maakt, dus je zou zoiets als dit willen:

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

Antwoord 4, Autoriteit 14%

Ik heb erin geslaagd om een ​​recursieve array diepe kopie te bedenken. Het lijkt vrij goed te werken, zelfs voor multi-dimensionale arrays met verschillende dimensielengte b.v.

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

Hier is de hulpprogramma-methode.

@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: Bijgewerkt de code om te werken met primitieve arrays.


Antwoord 5, Autoriteit 9%

Ja, dat is de enige manier om het te doen. Noch java.util.ArraysNot Commons-Lang bieden diepe kopie voor arrays.


Antwoord 6, Autoriteit 5%

Je kunt deze array herhalen en een reeks aanroepen uitvoeren van Arrays.copyOfmethode:

boolean[][] arr1 = {{true, true}, {false, true}};    // original array
boolean[][] arr2 = Arrays.copyOf(arr1, arr1.length); // shallow copy
boolean[][] arr3 = Arrays.stream(arr1)               // deep copy
        .map(arr -> Arrays.copyOf(arr, arr.length))
        .toArray(boolean[][]::new);
arr1[0][0] = false;
System.out.println(Arrays.deepToString(arr1)); // [[false, true], [false, true]]
System.out.println(Arrays.deepToString(arr2)); // [[false, true], [false, true]]
System.out.println(Arrays.deepToString(arr3)); // [[true, true], [false, true]]

Of je kunt Object.clonemethode:

boolean[][] arr3 = Arrays.stream(arr1)
        .map(boolean[]::clone)
        .toArray(boolean[][]::new);

Of je kunt een algemene methodevoor dit doel:

static <T> T[][] deepCopy(T[][] matrix) {
    return Arrays.stream(matrix)
            .map(arr -> arr.clone())
            .toArray(s -> matrix.clone());
}

Zie ook: Waarom muteert Array.copyOf() de originele array in het geval van 2D-arrays?


Antwoord 7, autoriteit 3%

Hier is een reflecterend voorbeeld met behulp van java.lang.reflect.Arraydie robuuster is en een beetje gemakkelijker te volgen. Deze methode kopieert elke array en kopieert de multidimensionale arrays diep.

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

Antwoord 8

java.util.arrays.Deepequals ()

referentie

Other episodes