【问题标题】:Future code affecting state at an earlier point in time?未来代码会在更早的时间点影响状态吗?
【发布时间】:2021-09-17 10:47:04
【问题描述】:

(编辑:请注意,TwoStacksAsQueue 和 ArrayList 的 add() 方法不同,因此不会发生递归调用。使用调试器后我仍然卡住,这就是我在这里寻求帮助的原因。)

我正在设计一个由两个堆栈组成的类,用作队列。当我运行它时,它打印的最后一个数字是预期的 6。但是,当我取消注释最后三行代码时,它会打印 3。

在我看来,transfer() 方法末尾的 while 循环是否被注释掉应该没有区别。它出现在 print 语句之后,那么它怎么可能影响输出呢?我在这里想念什么?我已将我的代码缩减为最小的可重现示例。

public class TwoStacksAsQueue<T> {
    final int stackCapacity;
    final Stack<T> stack1;
    final Stack<T> stack2;

    public TwoStacksAsQueue(int stackCapacity) {
        this.stackCapacity = stackCapacity;
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    public void add(T something) {
        if (stack1.size() + stack2.size() >= stackCapacity * 2)
            throw new RuntimeException("Not enough room in either stack; cannot add");
        else if (stack1.isEmpty()) {
            stack1.push(something);
        } else {
            int size = stack1.size();
            List<T> popped = new ArrayList<>();
            while (!stack1.isEmpty()) popped.add(stack1.pop());
            stack1.push(something);
            for (int i = size - 1; i >= 0; i--) stack1.push(popped.get(i));
            if (stack1.size() > stackCapacity) transfer(stack1, stack2);
        }
    }

    private void transfer(Stack<T> from, Stack<T> to) {
        List<T> popped = new ArrayList<>();
        System.out.println(from.size());
//        while (from.size() > stackCapacity) {
//            popped.add(from.pop());
//        }
    }
}

主要方法:

TwoStacksAsQueue<Integer> twoStacksAsQueue = new TwoStacksAsQueue<>(3);
twoStacksAsQueue.add(0);
twoStacksAsQueue.add(1);
twoStacksAsQueue.add(2);
twoStacksAsQueue.add(3);
twoStacksAsQueue.add(4);
twoStacksAsQueue.add(5);

【问题讨论】:

  • 我无法真正遵循您的代码,但我确实注意到 add 调用自身,以及调用 transfer。因此,您可以多次致电transfer。也许这三行的缺失或存在会影响对transfer 的后续调用。老实说,解决这个问题的最佳方法是使用调试器单步执行代码。
  • 您可能没有一台神奇的计算机,将来运行的代码会影响过去的状态。所以这绝对不是正在发生的事情。
  • @Jesper 然而我们还是……
  • @DawoodibnKareem 我的 TwoStacksAsQueue 类的 add() 方法与 ArrayList 中的 add() 方法无关,所以这不是同一个方法调用自身的情况。 Add() 确实调用了 transfer(),但这本身并不能解释任何错误。我在 main 方法中所拥有的纯粹是用于初始化 TwoStacksAsQueue 对象。由于错误的根源在于这三行代码的存在与否,我不确定调试器将如何提供帮助。我知道它们确实会导致从堆栈缩小,但直到已经打印了从堆栈的大小之后!
  • “我不确定调试器将如何提供帮助” - 一方面,它可能会帮助您了解您的某些假设是错误的(例如,堆栈可能不包含您认为的元素数量包含)。最终输出之前的输出是什么?这也可能是一个线索。 “它怎么可能影响输出” - 好吧,您正在反复调用 add (并因此转移),并且在转移中,您每次都丢弃元素。 while 循环有效地限制了元素的数量。

标签: java methods stack comments


【解决方案1】:

当超过stackCapacity 时,注释掉的代码行会改变行为。在您的示例中,当您按下第四个项目时会发生这种情况。您应该将调试工作集中在那里,而不是等到第六项被推送。如果您认为在点击两次 stackCapacity 之前不应触发该代码,您需要重新考虑该部分。

您的代码很难遵循。特别是,我不知道您为什么要创建临时的popped 列表而不是使用stack2。似乎您认为您正在将值传输到 stack2,但实际上您将它们放在一个临时的 popped 列表中,然后超出范围。通过打印出stack1stack2 的所有元素,您可以更轻松地进行调试,而不是尝试根据大小来识别某些内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2011-11-10
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多