Reputation: 4577
Say I have the following array declaration:
new double[][] {new double[] {1, 2, 3}, new double[] {4,5,6}, new double[] {7,8,9}}
and I want to "translate" (shift) the contents of the array by a fixed amount in a given direction, leaving the existing contents in the non-overwritten cells - e.g:
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
I can do these operations fairly easily using System.arraycopy:
shift by 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));
}
shift by 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));
}
}
The interesting behaviour comes when I try to do both together (e.g. dx = 1 and dy = 1
).
If I use the above code in the order shown (dy then dx), it seems like the copied array gets updated in the for-loop iteration for the array it was copied from.
e.g for the 1..9 example, for dx = 1 and dy = 1, the changes I observe are as follows:
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
As you can see, during the for
loop in the dx
transform, it's treating the first and second rows like they are the same object; and so applying the transformation twice - applying it to both arrays both times.
The documentation for System.arraycopy states:
If the src and dest arguments refer to the same array object, then the copying is performed as if the components at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.
In other words, when the dy
transform is done, the top two rows are copied off to a separate temporary array, and then back in to the main array a
but in the shifted position.
It seems to me that it is copying the reference
to the array, rather than the array itself - is that what's happening?
Anyway, I can solve the issue by swapping the code so it does the dx shifts before the dy; but it would be interesting to confirm what is going on here; because if I wanted to expand this into 3 dimensions, I wouldn't just be able to rearrange it to make it work.
Upvotes: 1
Views: 155
Reputation: 393936
Yes, it is copying references.
A 2D array is actually an array whose elements are objects of array type.
Therefore, when System.arraycopy
copies the elements of the source array to the target array (regardless of whether they are the same array or not) it copies references to these elements, which in your case means references to the inner arrays.
Upvotes: 2