简体   繁体   English

如何深度复制不规则的2D数组

[英]How to deep copy an irregular 2D array

How can I deep copy an irregularly shaped 2D array in Java? 如何在Java中深度复制不规则形状的2D数组?

Ie. IE浏览器。

int[][] nums =  {{5},
                 {9,4},
                 {1,7,8},
                 {8,3,2,10}}

I'm unable to use Arrays.arrayCopy() for some reason (versioning?) 我出于某种原因无法使用Arrays.arrayCopy() (版本化?)

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(). 您可以使用System.arraycopy()或Arrays.copyOf()替换第二个循环。

I wrote this in Eclipse, tested it, came back and found that João had beaten me to almost exactly the same solution. 我在Eclipse中编写了这个,对它进行了测试,然后回来发现João已经把我击败了几乎完全相同的解决方案。 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. 为了额外的功劳,尝试编写一个复制n维数组的地方,其中n是任意的。

N-dimensional deep copy N维深拷贝

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

Some folks suggest clone() -- just to be extra clear, clone() on a multi-dimensional array is only a shallow clone. 有些人建议clone() - 只是为了清楚,多维数组上的clone()只是一个浅层克隆。 original.clone()[0] == original[0] . original.clone()[0] == original[0] But (for primitives) you can use clone() instead of System.arraycopy() once you're down to one-dimensional arrays. 但是(对于基元),一旦进入一维数组,就可以使用clone()而不是System.arraycopy()

Here is a simple convenient way to copy 2 dimensional arrays (compatible with DEEP copy) : 这是一种复制二维数组的简便方法(与DEEP副本兼容):

public static char[][] cloneArray(char[][] array){
 char[][] copy = new char[array.length][];
 for(int i = 0 ; i < array.length ; i++){
  System.arraycopy(array[i], 0, copy[i] = new char[array[i].length], 0, array[i].length);
 }
 return copy;
}

plz note that you simple have to change array type to anything else, like int 请注意,您必须将数组类型更改为其他任何内容,例如int

Here's one that specializes to deeply cloning int[][] . 这是一个专门深入克隆int[][] It also allows any of the int[] to be null . 它还允许任何int[]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!
    }
}

Another arbitrary nd copy. 另一个任意nd副本。 It's ugly, and thanks to Java's type system you can't cast the result back to the array type you started with. 这很难看,而且由于Java的类型系统,你无法将结果转换回你开始使用的数组类型。 Still, it works. 它仍然有效。 Like the other comments say, use clone() :) 像其他评论说的那样,使用clone():)

public  void testMultiDimArray()
{
   int[][][] arr = new int[][][] {
           { {5}, {5, 6 }, {3, 3, 1} },
           { {1, 2, 3}, {4, 5 } }
   };

   Object[] dest = (Object[]) deepCopy(arr);
   // System.out.println(Arrays.deepToString(dest));
   assertTrue(Arrays.deepEquals(arr, dest));
}

public static Object deepCopy(Object src)
{
    int srcLength = Array.getLength(src);
    Class srcComponentType = src.getClass().getComponentType();

    Object dest = Array.newInstance(srcComponentType, srcLength);

    if (srcComponentType.isArray())
    {
        for (int i = 0; i < Array.getLength(src); i++)
            Array.set(dest, i, deepCopy(Array.get(src, i)));
    }
    else
    {
        System.arraycopy(src, 0, dest, 0, srcLength);
    }

    return dest;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM