在不更改堆栈的情况下更改添加到堆栈的变量的值?

Change value of variable added to stack without changing stack?

我有一堆数组。我还有一个数组,我将其压入堆栈、修改并再次压入。每当我更改数组的值时,堆栈中的所有变量都会以相同的方式修改。例如:

int[] array = {1, 1};
Stack<int[]> stack = new Stack<int[]>();
stack.push(array);
array = {1, 3};
stack.push(array);

堆栈应该是 {{1, 1}, {1, 3}},但实际上是 {{1, 3}, {1, 3}}。我试过 stack.push({1, 3}); 但这会导致错误。我也不能每次都声明一个新数组,因为整个事情都是循环发生的。

您的代码无法编译。不编译解释的部分先忽略不计java.

I also can't declare a new array every time because this whole thing is happening in a loop.

诺诺。你可以。 int[] 是对象类型(与原始类型相反)。这意味着该变量实际上代表一张藏宝图,而不是宝藏。那么,让我们分解一下:

int[] array = {1, 1};

这只是语法糖:

int[] array = new int[] {1, 1};

这只是语法糖:

int[] array = new int[2];
array[0] = 1;
array[1] = 1;

此外,new int[2]命令创建新宝藏并将其埋在沙子中,int[] array部分制作新的藏宝图,中间的=涂鸦一个不错的X-marks-the-spot 在你的地图上。 []. 是 java-ese 的意思是:走到 X 并向下挖掘。 = 是 java-ese 的意思是:拿一块橡皮擦掉那个 X,然后把它放在别的地方。

此外,在 java 中,每当您将内容传递给方法时,它总是副本(但是,map 的副本,而不是 宝物).

这种思考方式正是 java 内存模型的工作方式,绝不会误导您。因此:

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.

当然堆栈看到相同的3:只有一个宝藏,你们都有一张地图。

让我们修复它。请记住,= 消除 X,new 创造新宝藏。我们这里要2个宝物:一个是{1, 1},一个是{1, 3}。所以,new 是有作用的,= 也是有用的。让我们使用它们:

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);

成功!现在可以了。

原因int[] x = {1, 3};合法,而x = {1, 1};不合法,是语言的怪癖。它在语言规范中。 int[] x = ... 是用初始值设定项声明一个新变量,而 x = ... 是一个赋值表达式。

Java 需要知道你要创建的数组的类型。写int x = { ... }的时候就很明显了。当你写 x = { ... } 时,它稍微不太明显,这大概是 为什么 规范不允许 shorthand。请注意,写 int[] x = new int[] {1, 3}; 也完全没问题; int x[] = {1, 3}; 只是方便 shorthand.

// 这需要你的数组映射,跟随 X, // 挖掘,抛出你找到的第二个元素 // 在盒子里,然后在里面放一个 3。

我猜你的 sintax 只是循环中代码的简化。

由于您的要求是使用相同的数组实例,而不创建更多数组,您需要的是在每次迭代时推送该数组的浅表副本。基元的浅克隆不会受到对同一对象的进一步修改的影响,因此将复制正确的值,而不会因您在后续迭代中所做的更新而改变。

就是这个:

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());

您的堆栈现在将保存正确的值

stack [0] --> {1,1}
      [1] --> {1,3}

或者,每次您都可以将一个新数组分配给 array,例如

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)));
    }
}

输出:

[1, 1]
[1, 3]