更改添加到堆栈的变量值而不更改堆栈?

时间:2021-03-18 02:03:20

标签: java arrays 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}); 但这会导致错误。我也不能每次都声明一个新数组,因为这整件事都是在循环中发生的。

2 个答案:

答案 0 :(得分:2)

您的代码无法编译。不编译解释java的部分先不说。

<块引用>

我也不能每次都声明一个新数组,因为整个过程都在循环中发生。

诺诺。你可以。 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-在您的地图上标记该地点。 []. 是 Java 语言,用于:走到 X 并向下挖掘。 = 是 java-ese 的意思:拿一块橡皮擦把那个 X 擦掉,然后把它放在别的地方。

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

这种思考方式正是 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 = { ... } 时,这可能不太明显,这大概是为什么规范不允许速记。请注意,写 int[] x = new int[] {1, 3}; 也完全没问题; int x[] = {1, 3}; 只是方便的简写。

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

答案 1 :(得分:2)

我猜你的语法只是对循环中代码的简化。

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

就这样:

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}

enter image description here

enter image description here

或者,每次您都可以将一个新数组分配给 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]
相关问题