如何深度复制一个不规则的二维数组

5
如何在Java中深度复制一个不规则形状的二维数组?
例如:
int[][] nums =  {{5},
                 {9,4},
                 {1,7,8},
                 {8,3,2,10}}

由于某些原因(版本问题?),我无法使用 Arrays.arrayCopy() 方法。


这个问题能帮到您吗?链接 - guerda
1
没有Arrays.arrayCopy()。有System.arrayCopy()(自Java 1.0以来就存在),还有Arrays.copyOf()(自Java 6/Java 1.6以来就存在)。请澄清您的意思。 - Joachim Sauer
似乎是完全重复的 - 请参考guerda的答案。 - The Archetypal Paul
@Paul: 这不是那个问题的副本 - 你甚至读了它吗? - Draemon
同意,这不是一个完全相同的重复问题,它是一个更具体的问题,有着截然不同的答案(来自其他问题的答案仍然可能有帮助)。 - Joachim Sauer
7个回答

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

你可以使用 System.arraycopy() 或 Arrays.copyOf() 方法替换第二个循环。


1
如果数组中包含的是原始类型或不可变对象,您也可以使用Object#clone方法,就像在这种情况下一样。 - Zach Langley

7

我在Eclipse中编写了这个程序,测试后回来发现João已经几乎完全相同地解决了问题。我为他点赞,但这是我的代码用于比较。我觉得看到人们选择做不同的微小细节是很有启示性的。

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

对于额外的加分,尝试编写一个可以复制任意n维数组的函数,其中n是任意的。


呵呵,N维度不难,但在Java中有点丑陋,个人意见=)请参见下文。 - Chii

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

你能包含TestCase吗?我想试试这个。 - pn1 dude
TestCase是JUnit的一部分 - 测试框架(我在这里使用它以便于测试,但它不是必需的功能)。 - Chii

1

有些人建议使用clone() -- 仅为了更加清晰,多维数组上的clone()只是一个浅克隆。对于原始类型,一旦你降到一维数组,你可以使用clone()代替System.arraycopy()


1

这里有一个专门用于深度克隆 int[][] 的方法。它还允许任何一个 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!
    }
}

0

这里有一种简单方便的方法可以复制二维数组(与深度复制兼容):

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

请注意,您只需将数组类型更改为其他任何类型,例如int。

0

另一個任意的n維複製。它很醜陋,由於Java的類型系統,你無法將結果向回轉換為起始的數組類型。但仍然有效。像其他評論所說,使用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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接