【问题标题】:How to deep copy an irregular 2D array如何深度复制不规则的二维数组
【发布时间】:2010-09-30 00:14:44
【问题描述】:

如何在 Java 中深度复制形状不规则的二维数组?

即。

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

由于某种原因我无法使用Arrays.arrayCopy()(版本控制?)

【问题讨论】:

  • 可以this question帮助你吗?
  • 没有 Arrays.arrayCopy()。有 System.arrayCopy()(自 Java 1.0 以来就存在)和 Arrays.copyOf()(自 Java 6/Java 1.6 以来就存在)。请澄清你的意思。
  • 似乎完全重复 - 请参阅 guerda 的回答
  • @Paul:这不是那个问题的重复——你读过吗?
  • 同意,这不是一个完全重复的问题,它是一个更具体的问题,答案大相径庭(不过,其他问题的答案仍然会有所帮助)。

标签: java arrays deep-copy multidimensional-array


【解决方案1】:
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()。

【讨论】:

  • 如果它是一个基元数组或不可变对象数组,您也可以使用 Object#clone,就像在这种情况下一样。
【解决方案2】:

我在 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 恕我直言 =) 见下文
【解决方案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吗?我想试试这个。
  • TestCase 是 JUnit 的一部分 - 测试框架(我在这里使用它,因此很容易测试它,它不需要运行)。
【解决方案4】:

有些人建议clone() -- 更清楚一点,多维数组上的clone() 只是一个浅层克隆。 original.clone()[0] == original[0]。但是(对于原语)你可以使用clone() 而不是System.arraycopy() 一旦你下降到一维数组。

【讨论】:

    【解决方案5】:

    这里有一个专门用于深度克隆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!
        }
    }
    

    【讨论】:

      【解决方案6】:

      另一个任意 n-d 副本。这很难看,而且由于 Java 的类型系统,您无法将结果转换回您开始使用的数组类型。尽管如此,它仍然有效。就像其他 cmets 所说,使用 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;
      }
      

      【讨论】:

        【解决方案7】:

        这里是复制二维数组的简单方便的方法(兼容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;
        }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-07-30
          • 1970-01-01
          • 1970-01-01
          • 2014-02-16
          • 1970-01-01
          • 2015-11-20
          • 1970-01-01
          相关资源
          最近更新 更多