Home > other >  Why can't I loop over a Stack using a for loop?
Why can't I loop over a Stack using a for loop?

Time:09-15

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) {
    //
}
  1. initialization is executed only once
  2. termination is executed each iteration
  3. 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:

  1. 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());
  1. While loop.
while (!s.empty()) {
  System.out.println(s.pop());
}
  • Related