System.ArrayCopy 如何复制数组的数组?

Posted

技术标签:

【中文标题】System.ArrayCopy 如何复制数组的数组?【英文标题】:How does System.ArrayCopy copy arrays of arrays? 【发布时间】:2019-09-18 10:07:49 【问题描述】:

假设我有以下数组声明:

new double[][] new double[] 1, 2, 3, new double[] 4,5,6, new double[] 7,8,9

我想在给定方向上将数组的内容“平移”(移动)一个固定的量,将现有内容留在未覆盖的单元格中 - 例如:

1 2 3                                1 1 2
4 5 6   Shifted by +1 in x becomes:  4 4 5
7 8 9                                7 7 8


1 2 3                                1 2 3
4 5 6   Shifted by +1 in y becomes:  1 2 3
7 8 9                                4 5 6

我可以使用 System.arraycopy 相当轻松地完成这些操作:

按 dy 移动:

boolean b2t = dy<0; // bottom to top movement
dy = Math.abs(dy);

if (b2t)

    System.arraycopy(a, dy, a, 0, (a.length-dy));

else

    System.arraycopy(a, 0, a, dy, (a.length-dy));   

位移 dx:

boolean l2r = dx>0; // left to right movement
dx = Math.abs(dx);
for (double[] i : a)

    if (l2r)
    
        System.arraycopy(i, 0, i, dx, (i.length-dx));
    
    else
    
        System.arraycopy(i, dx, i, 0, (i.length-dx));   
    
   

当我尝试同时进行这两种操作时会出现有趣的行为(例如dx = 1 and dy = 1)。

如果我按照显示的顺序(dy 然后 dx)使用上面的代码,复制的数组似乎在 for 循环迭代中更新了它从中复制的数组。

例如对于 1..9 的例子,对于 dx = 1 和 dy = 1,我观察到的变化如下:

Orig.        dy   for:dx(1)      dx(2)      dx(3)
1 2 3      1 2 3      1 1 2      1 1 1      1 1 1
4 5 6   -> 1 2 3   -> 1 1 2   -> 1 1 1   -> 1 1 1
7 8 9      4 5 6      4 5 6      4 5 6      4 4 5

如您所见,在dx 转换中的for 循环期间,它将第一行和第二行视为同一个对象;因此应用了两次转换 - 两次都将其应用于两个数组。

System.arraycopy 的文档说明:

如果 src 和 dest 参数引用同一个数组对象,则执行复制,就好像首先将位置 srcPos 到 srcPos+length-1 的组件复制到具有长度组件的临时数组,然后复制临时数组通过目标数组的 destPos+length-1 复制到位置 destPos 中。

换句话说,当dy 转换完成时,前两行被复制到一个单独的临时数组中,然后返回到主数组a,但在移动位置。

在我看来,它正在将 reference 复制到数组,而不是数组本身 - 这是怎么回事?

无论如何,我可以通过交换代码来解决这个问题,这样它就可以在 dy 之前进行 dx 移位;但是确认这里发生了什么会很有趣;因为如果我想将其扩展到 3 个维度,我将无法重新排列它以使其工作。

【问题讨论】:

【参考方案1】:

是的,它正在复制引用。

二维数组实际上是一个数组,其元素是数组类型的对象。

因此,当System.arraycopy 将源数组的元素复制到目标数组时(无论它们是否是同一个数组),它都会复制对这些元素的引用,在您的情况下,这意味着对内部数组的引用。

【讨论】:

以上是关于System.ArrayCopy 如何复制数组的数组?的主要内容,如果未能解决你的问题,请参考以下文章

System.arraycopy方法实现数组的复制

使用System.arraycopy()实现数组之间的复制

System.arraycopy复制数组方法解释

使用 System.arraycopy(...) 比使用 for 循环复制数组更好吗?

使用System.arraycopy()实现数组之间的复制

复制数组之System.arraycopy()的使用