【问题标题】:Change value of variable added to stack without changing stack?更改添加到堆栈的变量值而不更改堆栈?
【发布时间】:2021-06-15 10:06:44
【问题描述】:

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

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 arrays stack


    【解决方案1】:

    您的代码无法编译。不编译解释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 创造了新的宝藏。我们这里要两个宝物:一个是{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。

    【讨论】:

      【解决方案2】:

      我猜你的 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]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-28
        相关资源
        最近更新 更多