Reputation: 23
I have a stack of arrays. I also have an array that I push into the stack, modify, and push again. Whenever I change the value of the array, all variables within the stack are modified the same way. For example:
int[] array = {1, 1};
Stack<int[]> stack = new Stack<int[]>();
stack.push(array);
array = {1, 3};
stack.push(array);
The stack should be {{1, 1}, {1, 3}}
but instead it's {{1, 3}, {1, 3}}
. I've tried stack.push({1, 3});
but that results in an error. I also can't declare a new array every time because this whole thing is happening in a loop.
Upvotes: 2
Views: 68
Reputation: 11900
I guess your sintax is just a simplification of the code inside your loop.
As your requirement is using the same array instance, without creating further arrays, what you need is to push a shallow copy of this array, at each iteration. Shallow clones of primitives don't get affected by further modifications on the same object, so the correct values will be copied without being altered by the updates you make on the following iterations.
Just this:
int[] array = {1, 1};
Stack<int[]> stack = new Stack<int[]>();
stack.push(array.clone());
//array = {1,3}; ---> in order to mimic this, I manually alter array's values
array[0]=1;
array[1]=3;
stack.push(array.clone());
Your stack will now hold the correct values
stack [0] --> {1,1}
[1] --> {1,3}
Alternatively, each time you can assign a new array to array
e.g.
import java.util.Arrays;
import java.util.Stack;
public class Main {
public static void main(String args[]) {
int[] array = { 1, 1 };
Stack<int[]> stack = new Stack<int[]>();
stack.push(array);
array = new int[] { 1, 3 };
stack.push(array);
stack.forEach(e -> System.out.println(Arrays.toString(e)));
}
}
Output:
[1, 1]
[1, 3]
Upvotes: 2
Reputation: 103903
Your code does not compile. Let's disregard the part that doesn't compile and explain java.
I also can't declare a new array every time because this whole thing is happening in a loop.
Nono. You can. int[]
is an object type (in contrast to a primitive type). That means the variable actually represents a treasure map, and not the treasure. So, let's break it down:
int[] array = {1, 1};
This is just syntax sugar for:
int[] array = new int[] {1, 1};
which is just syntax sugar for:
int[] array = new int[2];
array[0] = 1;
array[1] = 1;
Furthermore, the new int[2]
command creates new treasure and buries it in the sand, and the int[] array
part makes a new treasuremap, and the =
in the middle scribbles a nice X-marks-the-spot on your map. []
and .
are java-ese for: Walk to the X and dig down. =
is java-ese for: Take an eraser and wipe that X away, then place it somewhere else.
Also, in java, whenever you pass stuff to methods, it's always copies (but, copies of the map, not copies of the treasure).
That way of thinking about it is precisely how the java memory model works and will never steer you wrong. Thus:
int[] array = {1, 1};
// 1 treasure chest made.
// 1 treasure map made. The map is called `array`.
// X marked on the map.
stack.push(array);
// Take your `stack` map, walk to the X. Dig down.
// Open the chest you find here, and yell into it: "push".
// Make a copy of your `array` map, and hand it over.
array = {1, 3};
// This isn't legal java.
array[1] = 3;
// This takes your array map, follows the X,
// digs, tosses out the second element you find
// in the box, and then puts a 3 in there instead.
Of course the stack sees the same 3: There is only one treasure, and you both have a map to it.
Let's fix it. Remember, =
wipes out the X, and new
makes new treasure. We want 2 treasures here: One is {1, 1}
, and the other is {1, 3}
. So, new
is involved, and =
is useful too. Let's use them:
int[] array = {1, 1};
stack.push(array);
array = new int[] {1, 3};
// The above is the syntax for making a new int array.
stack.push(array);
System.out.println(stack);
success! Now it works.
The reason int[] x = {1, 3};
is legal, but x = {1, 1};
is not, is a quirk of the language. It's in the language specification. int[] x = ...
is declaring a new variable with an initializer, whereas x = ...
is an assignment expression.
Java needs to know the type of the array you want to make. It's very obvious when writing int x = { ... }
. It is slightly less obvious when you write x = { ... }
which is presumably why the spec doesn't allow the shorthand. Note that it is perfectly fine to write int[] x = new int[] {1, 3};
as well; int x[] = {1, 3};
is merely convenient shorthand.
// This takes your array map, follows the X, // digs, tosses out the second element you find // in the box, and then puts a 3 in there instead.
Upvotes: 2