What exactly is wrong with newarray = oldarray.clone() for md arrays? - java

After some search for copying of multidimensional arrays manipulation in java I found this question: copy a 2d array in java and a downvoted answer suggests using the method in the title. So my questions are:
1) why is it bad? (becuase it looks quick and obvious)
2) is the best way still System.arraycopy each line?

Fundamentally, an array is an object. If you have a multidimensional array and you clone it, you won't get copies of the internal arrays (because they are also array Object(s)). You could use Arrays.copyOf(T[],int). From the linked Javadoc,
Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain null. Such indices will exist if and only if the specified length is greater than that of the original array. The resulting array is of exactly the same class as the original array.
Edit
The above is analogous to System.arraycopy() but also creates shallow copies. If you need to create deep copies of the multidimensional array you would have to iterate over the array clone and create a deep copy for each row.

Related

What does new ClassName[0] do? (Java 8)

What does this syntax do, with square brackets around the number?
new Integer[0];
I've found it in a codebase I'm maintaining but I can't find any documentation on it. It is used like this:
Set<Form> forms = getForms();
List<Form> formsList = Arrays.asList(forms.toArray(new Form[0]))
It allocates an array with length zero; e.g. new Integer[0] creates a zero length array of Integer objects.
Why would you do that?
Well look at the javadocs for the form.toArray(T[]) method. Assuming that form is some subtype of Collection they are here.
The purpose of the toArray method is to copy the elements of the target collection (e.g. your form) into an array:
If the argument array is large enough to hold all elements, they are copied into that array. The result will be the argument array.
If the argument array is too small, a new array is allocated with the same type as the argument array and a length that is (just) enough to hold the elements. The elements are then copied into the new array, and it is returned as the result.
So what the code is actually doing is copying the elements of form to an Integer[] of the right size, and then wrapping the array to give a (fixed sized) List<Integer>. This can then be passed to some other code without worrying that that code might alter the original form collection.
Unlike traditional array which store values like string, integer, Boolean, etc. array of objects stores objects. The array elements store the location of reference variables of the object
Syntax:
Class obj[]= new Class[array_length]

Shuffling - no duplicates JAVA

I am trying to create a List of Integer arrays by taking one integer array and shuffling it a number of times. However, once I shuffle the array, the initial array is also modified since it works by reference! Is there any way I can add a variation of the initial array (which is already resident in the list) without creating a new array please?
Thanks!
Just copy the array using System.arrayCopy then use Collections.shuffle on the original.

Why java can pass multi-dimensional array to methods without specifying any size information

As far as I know, we can pass multiple dimensional array to a method in Java without size info, like this:
void foo(int arr[][][])
But in C++, you can only exclude the size of the outer-most dimension, like this:
void foo(int arr[][y_size][z_size)
Now I understand that in C++, 'arr' will decay to a pointer, so the compiler needs to know how much elements to skip between two pointers.
My question is, what happens underneath Java makes it smarter than C++ on this, so it can distinguish the bounds between elements without knowing the size of each dimension?
C is passing an address to one contiguous area of memory. The recipient needs all but one of the dimensions in order to compute the locations of array elements in memory.
Java is passing a reference to an array object that knows its contents and size. A multidimensional array is not one contiguous area of memory. The computation made by C does not occur. Instead, the multidimensional array is comprised of multiple 1D arrays. Each level but the last is an array of references to arrays.
Array length is still used by Java during array access. Every array access is checked at runtime. If the requested index is greater than or equal to the length (or less than zero), an ArrayIndexOutOfBoundsException is thrown.
Two things:
Every array, which is a run-time object, in Java has a length property associated with it.
In C, excluding C99 VLAs, arrays are only a compile-time type describing how to access objects therein per a particular layout.
Multi-dimensional arrays in Java are always jagged arrays.
This means that the length per/in the type is not even particularly relevant in Java - every "multi-dimensional array" access goes one array at a time so
r = a[x][y][z]
is merely
a_ = a[x]
b_ = a_[y]
r = b_[z]
and there is is no dimension-to-linear calculation involved.
In java arrays are objects which effectively consist of a pointer, and the size of the array.
So in java the extra information is included in the array object.

Making a replica 2D array before I change it

I've made a 2D array which is a map for a game. As the player moves around the map the Array changes slightly, but I'd like to be able to refer back to the original, unchanged Array. How can I do this?
Thanks a lot.
If you don't need a copy of each element, just the array, use
array.clone()
If you do need to copy each element, you can see this answer.
If arr is a 2d String array:
String[][] copy = arr.clone();
Then, just make changes to copy.
If it is an array of objects, you may want to make a deep copy, i.e. making a copy of all the contained objects. But in your case, since Strings are immutable, a clone will suffice. However, considering storing your data in classes instead of strings.

Difference between various Array copy methods

What is the difference between
System.arraycopy(),
clone()
manual copying by iterating through the elements
Arrays.copyOf()
and just doing arraynew = arrayold?
System.arraycopy() uses JNI (Java Native Interface) to copy
an array (or parts of it), so it is
blazingly fast, as you can confirm
here;
clone() creates a new array with the same characteristics as the old array, i.e., same size, same type, and same contents. Refer to here for some examples of clone in action;
manual copying is, well, manual copying. There isn't much to say about this method, except that many people have found it to be the most performant.
arraynew = arrayold doesn't copy the array; it just points arraynew to the memory address of arrayold or, in other words, you are simply assigning a reference to the old array.
System.arraycopy() copies data from one existing array into another one and depending on the arguments only copies parts of it.
clone() allocates a new array that has the same type and size than the original and ensures that it has the same content.
manual copying usually does pretty much the same thing than System.arraycopy(), but is more code and therefore a bigger source for errors
arraynew = arrayold only copies the reference to the array to a new variable and doesn't influence the array itself
There is one more useful option:
Arrays.copyOf() can be used to create a copy of another array with a different size. This means that the new array can be bigger or larger than the original array and the content of the common size will be that of the source. There's even a version that makes it possible to create an array of a different type, and a version where you can specify a range of elements to copy (Array.copyOfRange()).
Note that all of those methods make shallow copies. That means that only the references stored in the arrays are copied and the referenced objects are not duplicated.
Arrays.copyOf(..) uses System.arrayCopy(..) method internally.
There are answers but not a complete one.
The options considered are
Arrays.copyOf()
System.arraycopy()
Below is the java implementation of Arrays.copyOf()
public static double[] More ...copyOf(double[] original, int newLength) {
double[] copy = new double[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
As you can see copyOf uses System.arraycopy internally.
If you already have an array created use System.arraycopy() to copy
If you need the result in a new array use Arrays.copyOf() to copy
Note: There is no point in comparing the speed obviously because their functionalities differ.

Categories

Resources