java - System.ArrayCopy 如何复制数组的数组?
问题描述
假设我有以下数组声明:
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
如您所见,在转换for
循环期间dx
,它将第一行和第二行视为同一个对象;因此两次应用转换 - 两次都将其应用于两个数组。
System.arraycopy 的文档指出:
如果 src 和 dest 参数引用同一个数组对象,则执行复制,就好像首先将位置 srcPos 到 srcPos+length-1 的分量复制到具有长度分量的临时数组,然后临时数组的内容是通过目标数组的 destPos+length-1 复制到位置 destPos。
换句话说,当dy
转换完成时,前两行被复制到一个单独的临时数组中,然后回到主数组a
中,但在移位的位置。
在我看来,它是将 复制reference
到数组,而不是数组本身 - 这是发生了什么?
无论如何,我可以通过交换代码来解决这个问题,这样它就可以在 dy 之前进行 dx 移位;但是确认这里发生了什么会很有趣;因为如果我想将其扩展到 3 个维度,我将无法重新排列它以使其工作。
解决方案
是的,它正在复制引用。
二维数组实际上是一个数组,其元素是数组类型的对象。
因此,当System.arraycopy
将源数组的元素复制到目标数组时(无论它们是否是同一个数组),它都会复制对这些元素的引用,在您的情况下,这意味着对内部数组的引用。
推荐阅读
- angular - 在 Angular 中,使用 PrimeNG,如何设置禁用一些 p-selectButton 选项?
- elixir - Comeonin.Bcrypt checkpw 方法在我重置密码后返回 false - Elixir
- node.js - 在 Heroku 中每 30 秒运行一次任务
- java - Android MVP 我应该在哪里有一个 TextWatcher
- java - 矩阵大小的限制
- python - 更改Excel工作表中现有选项卡的列宽
- hybris - 带有 wro4j 的 Hybris 没有拉入插件 js 文件
- excel - Excel js api 大数据
- ansible - BIGIP 的 Ansible 模块 bigip_pool_member 始终返回“已更改”状态
- arrays - 列出字符串数组中所有元组的算法