为什么我不能使用 for 循环遍历堆栈?



我有一个包含3个项目的Stack,我想在每个项目上循环。如果我这样做:

public class Main {
public static void main(String[] args) {
Stack<Integer> s = new Stack<>();
s.add(1);
s.add(2);
s.add(3);

for (Integer num = s.pop(); !s.isEmpty(); num = s.pop()) {
System.out.println(num);
}
}
}

则它只打印出3和2,而不打印出1。为什么?

for循环弹出堆栈,如果堆栈为空则退出循环。

for (Integer num = s.pop(); !s.isEmpty(); num = s.pop()) {
System.out.println(num);
}

换句话说,num = s.pop()在测试!s.isEmpty()之前运行。因此,在最后一次迭代中,堆栈是空的,因此循环体不会执行。

对此有很多不同的方法。你可以做的一件事是使用while循环:

while (!s.isEmpty()) {
System.out.println(s.pop());
}

For循环由3个表达式组成:初始化、终止、增量

for (initialization; termination; increment) {
//
}
  1. 初始化仅执行一次
  2. 每次迭代都执行termination
  3. 每次迭代执行增量

在您的情况下,在第一次迭代中,您从堆栈中检索了两次,因此出现了非打印元素的问题。你可能想知道为什么它打印3,2而不是2,1?这是因为increment表达式在循环的每次迭代后被调用。

所有的部分都是可选的,所以你可以这样迭代:

for (; ; ) {
System.out.println(s.pop());
}

并且您最终将在尝试从已经空的堆栈中弹出元素时使用CCD_ 7。

因此,用for循环迭代堆栈的最基本方法是使用termination语句作为";"安全检查":

for (; !s.isEmpty(); ) {
System.out.println(s.pop());
}

这基本上是一种更复杂和违反直觉的方式来编写while-循环:

while (!s.isEmpty()) {
System.out.println(s.pop());
}

文档:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html

原因是在计算条件时堆栈已经为空。

几个选项(不是全部(如何正确弹出和打印所有项目:

  1. 循环时执行。如注释中所述,如果堆栈最初为空,将抛出EmptyStackException
do {
System.out.println(s.pop());
} while (!s.empty());
  1. While循环
while (!s.empty()) {
System.out.println(s.pop());
}

最新更新