• Post Reply Bookmark Topic Watch Topic
  • New Topic

How to make a deep copy of a multidimensional int array?  RSS feed

 
Louis Lewis
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello, I'm trying to set one 2d array equal to another without making one a reference to the other. I have read that in order to do this I should use something called a deep copy, which apparently involves looping through all the 1d arrays inside the original 2d array, and then using array.clone(). However, I am encountering errors that I don't know how to fix when I do this. Here is my main class, where I'm trying to use deep copy method to copy an int array:



Here is my other class, with the copyOf() method I am trying to build (this is where I'm encountering errors):



I tried looking up the int cannot be dereferenced error (as that seems to be the base problem),
but I don't even really understand what it means, much less why it's occuring in this instance.

Anyone know what's wrong, or a better way to do what I'm trying to do?
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Louis Lewis wrote:Hello, I'm trying to set one 2d array equal to another without making one a reference to the other. I have read that in order to do this I should use something called a deep copy, which apparently involves looping through all the 1d arrays inside the original 2d array, and then using array.clone().



I tried looking up the int cannot be dereferenced error (as that seems to be the base problem),
but I don't even really understand what it means, much less why it's occuring in this instance.

Anyone know what's wrong, or a better way to do what I'm trying to do?



Basically, it isn't valid Java. The "[]" -- ie. square brackets without an index -- has special meaning. It is used to tell java that the type is an array, which is important when declaring a variable, or instantiating an object. The compiler needs to know the type, and that is how the language define the declaration or instantiation of an array.

In your case, you are neither declaring a variable or instantiating an object. Java does not have a meaning for your code. There is no such a thing as dereferencing an array without an index.

Henry

 
Louis Lewis
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So how would I go about looping through the 1d arrays inside the 2d array then?
 
Paul Clapham
Sheriff
Posts: 22832
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Looping? With an ordinary for-loop. Like the one you used in lines 5-12 of your original post, in fact.
 
Louis Lewis
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, that avoids the problem of the empty brackets for the originalArray, but not for the newArray. This is what I have now:



I know how to loop through the 1d arrays inside the original array, but then I don't know how
to set the corresponding part of the new array equal to each section of the original array.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Louis Lewis wrote:Ok, that avoids the problem of the empty brackets for the originalArray, but not for the newArray. This is what I have now:



I know how to loop through the 1d arrays inside the original array, but then I don't know how
to set the corresponding part of the new array equal to each section of the original array.


First, don't forget to create the outer array -- the array that will hold the arrays. You will likely need to use the new operator to create that.

To answer your question, I don't think that it will be possible with the for-each loop. I would recommend using the regular for loop. This way, you have the array indexes that you will be copying element by element.

Henry
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Louis Lewis wrote:Hello, I'm trying to set one 2d array equal to another without making one a reference to the other. I have read that in order to do this I should use something called a deep copy, which apparently involves looping through all the 1d arrays inside the original 2d array, and then using array.clone().

For anyone who's interested, this struck me as an interesting generic problem that currently has no solution in Arrays: How to deep clone an n-dimensional array of any type (including primitive ones)?

Oddly enough, it's actually quite simple; but it requires a little knowledge of recursion to keep it simple, so be warned.

The first thing I worked out was that you need some way to clone the elements themselves; and you can't rely on the Cloneable interface since it doesn't define a clone() method. So, how about a Cloner interface instead? viz:
Next, we have the problem of cloning the array structure itself which, oddly, resolves very nicely, since all arrays are Objects. So, after a bit of fiddling, I came up with this:which you can type properly with a generically typed "wrapper" method: and furthermore, it works beautifully with n-dimensional primitive array types (where n > 1) as well, as long as you supply a Cloner that deals with that last primitive[] array.

For example, for an int[]...[]:
And now you can deep clone any multi-dimensional int array with:
int[][][][][] cloned = deepClone(my5Darray new IntArrayCloner());

How does it work? The secret lies in that:
if (element instanceof Object[])
line.

instanceof has got some poor press because of the tendency for people - especially beginners - to use it as a "dispatcher"; but in this case it's exactly what we want.
Any reference-type array, no matter how many dimensions it has, is a subclass of Object[], so the check ensures that as long as each element we're dealing with is an array, it keeps cloning recursively. If not, and we supplied a Cloner, it uses that to copy the element.

However, when we're dealing with primitive types like int[]...[], it still works, providing we have an applicable Cloner, because an int[][] is an array of int[]'s; and since ALL arrays are Objects, an int[][] MUST be an Object[].
Even nicer, an int[] is NOT an Object[]; it's an Object, so all we need to do is treat it as if it was an element.

Hope it's of some general use/interest.

Winston
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:Oddly enough, it's actually quite simple...

Famous last words.

Of course it isn't quite as simple as I described, because any leaf element in an Object[]...[] can be a reference to a supertree, or even the array itself, which could cause a stack overflow. It's fairly easily remedied by keeping an IdentityHashMap of "already cloned" items though.

Winston
 
Louis Lewis
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, thank you for your response, although I didn't understand what you did. Fortunately, I did come upon a solution that works as long as the array being copied is square (same length and width). And the arrays in question in my program are square, so it works for me. Here is my copyOf method:

 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Louis Lewis wrote:Well, thank you for your response, although I didn't understand what you did.

No probs. It was more for reasonably advanced bods who've run into the problem.

Fortunately, I did come upon a solution that works as long as the array being copied is square (same length and width). And the arrays in question in my program are square, so it works for me. Here is my copyOf method:

Very well done. However, with a small change, it will work for any int[][]. Just have your second loop use the width of the row it's working on, viz:
for (int y = 0; y < originalArray[x].length; y++)

Or, if you want, you can make it even simpler by still using clone() for the final array, viz:HIH

Winston
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!