I have a Stack with 3 items and I want to loop over each item. If I do this:
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);
}
}
}
then it only prints out 3 and 2 but not 1. Why is that?
CodePudding user response:
The for
loop pops the stack then exits the loop if the stack is empty.
for (Integer num = s.pop(); !s.isEmpty(); num = s.pop()) {
System.out.println(num);
}
Put another way, num = s.pop()
is run before the test !s.isEmpty()
. So on the final iteration, the stack is empty, therefore the loop body isn't executed.
There are many different ways around this. One thing you could do is use a while
loop instead:
while (!s.isEmpty()) {
System.out.println(s.pop());
}
CodePudding user response:
For loop consists of 3 expressions: initialization, termination, increment:
for (initialization; termination; increment) {
//
}
- initialization is executed only once
- termination is executed each iteration
- increment is executed each iteration
In your case you retrieve from the stack twice on the first iteration, hence your problem with a non-printing element.
You might be wondering why does it print 3,2
and not 2,1
? That's because increment expression is invoked after (in the very end) each iteration through the loop.
All of sections are optional, so you can iterate this way:
for (; ; ) {
System.out.println(s.pop());
}
... and you will eventually have java.util.EmptyStackException
on an attempt to pop an element from already empty stack.
So the most basic way to iterate over a stack with a for loop is to make use of termination statement as a "safe-check":
for (; !s.isEmpty(); ) {
System.out.println(s.pop());
}
... which is basically a more complex and counterintuitive way to write a while
-loop:
while (!s.isEmpty()) {
System.out.println(s.pop());
}
Docs: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
CodePudding user response:
The reason is that the stack is already empty, when the condition is evaluated.
Few options(not all) how to correctly pop and print all items:
- Do-while loop. As mentioned in comments, will throw
EmptyStackException
, if the stack is initially empty.
do {
System.out.println(s.pop());
} while (!s.empty());
- While loop.
while (!s.empty()) {
System.out.println(s.pop());
}