If I've got float[] a = {1,2,3};, can I copy it using only float[] b = a; to obtain a deep copy? How do I know when I need to use a.clone()?
To clarify: I want to be able to change a (e.g. a[0]=4;) without affecting b.
Just making float[] b = a; is not enough because then the array object will be shared between the 2 references a and b.
But because you have an array of primitive types is enough to use float[] b = a.clone(). The clone in this case will make a deep copy and will duplicate the array object including the primitive values inside.
If you had an array of some reference type you would need to clone the array and than iterate and clone every object to get a deep copy.
Shallow copying means only making the new reference to point to the memory location of the old array, while deep copying means allocating a new memory location and copying the contents of the first array to other.
Use deep copy only when you are afraid that someone will nullify/delete the first array. In that case your second array will also be pointing to non existent memory or null. If you have a requirement to save the contents in the second array then go for deep copy otherwise use shallow copy.
Read more about shallow and deep copy here: http://en.wikipedia.org/wiki/Object_copy
This is how you can make shallow or deep copy of your array:
Shallow copy
float[] b = a;
Deep copy
float[] b = Arrays.copyOf(a);
float[] b = a; means you are assigning the reference of the Array object held by variable a to variable b.
Use Arrays.copyOf() or System.arraycopy() to clone an array in Java. Also look at the micro-benchmarking.
How do I know when I need to use a.clone()?
Whenever you write a = b in Java where a and b are not primitives (i.e. boolean, char, byte, int, long, float, double), you are copying a reference.
In your example, when writing float[] a = {1,2,3}; then float[] b = a;, you only create one array, but have two variables "pointing" to it. So any change made to the array will be reflected on a and b.
To get a deep copy of your array and achieve your goal, simply clone it:
float[] b = a.clone();
no you need to do it for example like:
float[] b = (float[])a.clone();
I don't think that you can clone primitives, but if you had to you could always create a new array and a loop to copy all the values of one into the other.
Related
I'm setting an array equal to another array.
So let's say array B = array C.
Then, if I do operations on array B, changing it's values, does C also change?
I want to say absolutely not, but I'm having a brain fart and I feel like that what's happening in my code right now.
When you assign one array to another array the array will hold the reference so if you change the value in one array then it will surely change the value of other.
like in your example array B = array C. B will hold the reference to array C. so any changes in array B will reflect in array C.
Yes, they are changed.
The array is an object, so you assign only the reference, after assignment "array B = array C." both variables would hold the same reference. As a result you will have one object and two references
UPDATE
For "real copy" you need to use System.arraycopy() or Arrays.copyOf()
int[] arrayC = {1,2,3,4,5,6,7,8,9,10};
int[] arrayB = new int[arrayC.length];
System.arraycopy(arrayC, 0, arrayB, 0, arrayC.length );
This question already has answers here:
Are arrays passed by value or passed by reference in Java? [duplicate]
(7 answers)
Closed 3 years ago.
I can post more code if I need to, but before that I would like to just ask a general question about the following method in which an array is passed, and then set to another array, but for some reason the original array, the one being passed in, is also getting changed, how this possible/what should i do?
Thanks
tempBoard is an array of same size as currentState, and temp[k] contains the changes that are being made in movePiece, current state is declared in the method and is not a global variable
private int[][] MiniMaxBaseCase(int[][] currentState, int currentColor)
{
tempBoard = movePiece(currentState,temp[k]);
}
private int[][] movePiece(int[][] currentState, int[] move)
{
if(move[0] == -1)
return currentState;
//if the piece is just moving
if(move[4] == -1)
{
currentState[move[2]][move[3]] = currentState[move[0]][move[1]];
currentState[move[0]][move[1]] = 0;
return currentState;
}
//if the piece is jumping another
if(move[4] != -1)
{
currentState[move[4]][move[5]] = currentState[move[0]][move[1]];
currentState[move[2]][move[3]] = 0;
currentState[move[0]][move[1]] = 0;
return currentState;
}
return currentState;
}
In Java:
method arguments are indeed passed-by-value, but
all object and array variables in Java are reference variables.
The net effect of a reference variable being passed-by-value is that the object or array pointed to by that reference variable is passed-by-reference.
Your array was effectively passed-by-reference - its the same array.
Specifically, currentState in MiniMaxBaseCase is a reference to an array - the value of it is the memory location of the array. currentState in MiniMaxBaseCase is passed by value to movePiece, so the value of currentState in MiniMaxBaseCase (a memory location) if copied into parameter currentState in movePiece - the reference was passed by value. But now currentState in movePiece points to the same memory location as currentState in MiniMaxBaseCase. So now both variables both point to the same array, i.e. the net effect was that the array was effectively passed-by-reference.
Edit: Copying multi-dimensional arrays
Some people have been suggesting to use System.arraycopy() or Array.copyOf() directly without traversing into the first dimension/index. This won't work.
Use this instead:
public static int[][] copyOf(int[][] original) {
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copy[i] = Arrays.copyOf(original[i]);
}
return copy;
}
The reason a direct copy won't work is because in Java, a 2-dimensional array is really an array of pointers/references to a collection of (scattered) 1-dimensional arrays, i.e., int[][] is an array of pointers to a bunch of (scattered) int[]. Simply doing a System.arraycopy() or Arrays.copyOf() on a 2-D array will simply copy the pointers to the scattered int[] arrays, i.e. this shallow copy ends up sharing the underlying set of arrays. You must do a deep copy as shown in the code above.
Some references:
How do I do a deep copy of a 2d array in Java?
Yes, you should iterate over 2D boolean array in order to deep copy it.
http://www.cs.dartmouth.edu/~spl/Academic/Java/JFAQs.html
How do I copy multi-dimensional arrays?
...
Copying a two dimensional array is however more problematical because multi-dimensional arrays are represented as arrays of arrays. This is an issue when you are cloning an array. System.arraycopy() will give you a copy of the references to the embedded arrays. ...
In Java there is NO SUCH THING as pass-by-reference. You seem to know that and wonder why it still feels like that this is what happens here...
Well the Problem is, that arrays are Objects. And Objects are actually Pointers. So you get a COPY of the pointer to the array, but it's still the array it is pointing to.
Use System.arraycopy() if you want to create a copy of the array before making any changes to it.
Take some time to have a good read of this.
http://www.cs.toronto.edu/~dianeh/tutorials/params/
Skip down to "Passing Arrays"
Arrays are references. This means that when we pass an array as a parameter, we are passing its handle or reference. So, we can change the contents of the array inside the method.
This is from a course "148: Introduction to Computer Science", which should fit around the first 2 lessons on the Java language.
To pass a copy of an array to a function, in Java 1.6, you can use Array.copyOf, e.g
tempBoard = movePiece(Arrays.copyOf(currentState, currentState.length), temp[k]);
Note: Array.copyOf is only good for single-dimension array of primitives. Used on anything else, it gives you an independent array, with all elements IDENTICAL and pointing to the original array, be it Objects or nested arrays.
So I have an ArrayList in java. And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense.
Also, I'd rather not clear the original arraylist and then loop through it pushing the new contents into it.
I need to do something like this:
ArrayList a;
ArrayList *b = a;
//pass b (the pointer) to something
ArrayList c;
*b = c;
I really hope I got that (pseudo) c++ code correct or I'll look pretty stupid =P
I can see how I'm not being clear, it's kind of complicated (this is in android so it's across a couple activities) so let me see if I can get my point across better.
Class1{
ArrayList a;
method1(){
a = Class2.getA();
method_that_uses_a(a);
}
}
Class2{
ArrayList getA(){
ArrayList a = new ArrayList
a = getDataFromWebsite();
return a;
}
Class1's method1() gets called periodically by another portion of code. But I need the reference to a stay the same, but the contents to change to the new contents.
I think your question is unclear, what do you mean by
"And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense."
When you do
List a = new ArrayList
List b = a
you have one ArrayList object, and two references to the object, a and b.
Also note that there is an addAll method that you can use to add members of one collection to another collection. Note that I believe addAll does not do a deep copy, so if you use it both lists have copies of the same reference. So if list a has references a1, a2, a3, and you do b.addAll(a), b now has references to the objects that a1...a3 point to...
The array classes all expose public clone() methods, however, so if a
shallow copy of the array is sufficient then
return (ElementType[]) myArray.clone();
Makes for a nice, simple, easy to read paradigm. If "ElementType" is a
primitive type then there is no distinction between shallow and deep
copying, and if it is immutable then performing a deep copy would be
wasteful. In some other circumstances a shallow copy is what you would
want anyway (you want the receiver to be able to mutate the returned
array elements with effects visible to the host object).
If you find that you really do want to make a deep copy of the array
then you might want to consider whether your design can be improved; it
is not necessarily so, but I wouldn't be surprised.
In Java as I hope you;ve found out by now, all variables are references. Among other things this means that unless they are assigned to an object they don't 'point' at anything. You need to write:
ArrayList a = new ArrayList();
or a doesn't 'point to' an actual object - it's just null.
If you write:
ArrayList a = new ArrayList();
ArrayList b = a;
modify(b);
ArrayList c = b;
then there is only one ArrayList. All the variables a, b and c refer to it. Any modifications done in the 'modify' method apply to it, and will be reflect in the state of a, b and c.
You're C++ code says this:
ArrayList a; //make arraylist
ArrayList *b = a; //set b to point to same arraylist as a
//pass b somewhere
ArrayList c; //make arraylist
*b = c; //variable b in THIS PROGRAM now points to c. arraylist is unchanged.
You want to update the arraylist, not the pointer to it, as that pointer only 'exists' in the current context. The code you passed the arraylist to doesn't give a darn if a pointer back in who-knows-where now points to the same arraylist that its using. It's the actual object the other code cares about. To update that object, you can just call methods on it, like a.add(bar)
BUT there's more to it. If you call a function you don't control (now known as foo) and pass it an arraylist, that's all fine. But if you want to update it from the code calling foo, you run into issues. Imagine if an object you were working with could change randomly at any time. All sorts of bad stuff could happen. If you really need this capability (and we can help you judge if you do), look into the topic of threading.
I have a byte array which i want to copy/clone to avoid calling code from modifying my internal representation.
How do I clone a java byte array?
JLS 6.4.5 The Members of an Array Type
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array (length may be positive or zero).
The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Thus:
byte[] original = ...;
byte[] copy = original.clone();
Note that for array of reference types, clone() is essentially a shallow copy.
Also, Java doesn't have multidimensional arrays; it has array of arrays. Thus, a byte[][] is an Object[], and is also subject to shallow copy.
See also
Wikipedia/Object copy
Java Nuts and Bolts/Arrays
Related questions
Deep cloning multidimensional arrays in Java… ?
How to effectively copy an array in java ?
How to deep copy an irregular 2D array
How do I do a deep copy of a 2d array in Java?
Other options
Note that clone() returns a new array object. If you simply want to copy the values from one array to an already existing array, you can use e.g. System.arraycopy (jdk 1.0+).
There's also java.util.Arrays.copyOf (jdk 1.6+) that allows you to create a copy with a different length (either truncating or padding).
Related questions
Difference between various Array copy methods
System.arraycopy(src, 0, dst, 0, src.length);
It's easy, and it's a great idea to do it.
byte[] copy = arr.clone();
Note that the return type of the clone() method of arrays is the type of the array, so no cast is required.
In order to avoid a possible Null Pointer Exception I use the following syntax:
byte[] copy = (arr == null) ? null : arr.clone();
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.