Java
java.util.Stack
Iterator
bug
programming

Is there a bug in java.util.Stack's Iterator?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Usually, no, there is not a bug in java.util.Stack’s iterator. The surprising behavior comes from the fact that Stack extends Vector, so its iterator follows Vector’s normal iteration order from index 0 upward. That means iteration is not a “pop order” traversal of the stack, which is why developers expecting top-to-bottom LIFO iteration often think something is wrong.

Why The Iterator Feels Wrong

A stack is conceptually LIFO: the last pushed element is the first popped. But Iterator on Stack does not mean “iterate in pop order.” It means “iterate the underlying collection in its normal order,” which for Vector is from the first element to the last.

java
1import java.util.Stack;
2
3public class Main {
4    public static void main(String[] args) {
5        Stack<String> stack = new Stack<>();
6        stack.push("A");
7        stack.push("B");
8        stack.push("C");
9
10        for (String s : stack) {
11            System.out.println(s);
12        }
13    }
14}

This prints:

text
A
B
C

That is insertion-order iteration through the underlying Vector, not repeated popping from the top.

Why This Is By Design

Stack is an old class that inherits behavior from Vector. Its iterator is therefore inherited collection iteration behavior, not a special stack-specific traversal API.

So the design is arguably inconvenient for stack intuition, but it is not a bug in the sense of violating the implemented contract. The iterator still visits each element once in the collection’s standard iteration order.

Pop Order Requires A Different Approach

If you need LIFO traversal, use repeated pop() or choose a better data structure such as Deque.

java
1import java.util.Stack;
2
3public class Main {
4    public static void main(String[] args) {
5        Stack<String> stack = new Stack<>();
6        stack.push("A");
7        stack.push("B");
8        stack.push("C");
9
10        while (!stack.isEmpty()) {
11            System.out.println(stack.pop());
12        }
13    }
14}

This prints:

text
C
B
A

Now you are observing true stack behavior.

Why Deque Is Usually Better

Modern Java code usually prefers Deque implementations such as ArrayDeque for stack semantics.

java
1import java.util.ArrayDeque;
2import java.util.Deque;
3import java.util.Iterator;
4
5public class Main {
6    public static void main(String[] args) {
7        Deque<String> stack = new ArrayDeque<>();
8        stack.push("A");
9        stack.push("B");
10        stack.push("C");
11
12        Iterator<String> it = stack.iterator();
13        while (it.hasNext()) {
14            System.out.println(it.next());
15        }
16    }
17}

With ArrayDeque, the API is a better fit for stack and queue operations, and you also avoid the legacy synchronization overhead and confusing Vector inheritance story of Stack.

Reverse Traversal Without Popping

If you need reverse-order viewing without mutating the stack, a list-based reverse traversal is more explicit than relying on the default iterator.

java
for (int i = stack.size() - 1; i >= 0; i--) {
    System.out.println(stack.get(i));
}

This keeps the stack intact while still walking from top to bottom.

The Real Design Lesson

The confusion around Stack is not that its iterator is broken. The real lesson is that Stack is a legacy type whose inheritance from Vector leaks into behavior that does not match modern stack expectations very well.

That is why many Java developers treat Deque as the better default stack abstraction.

Common Pitfalls

  • Expecting Iterator on Stack to behave like repeated pop().
  • Assuming surprising iteration order means the implementation is buggy.
  • Forgetting that Stack inherits from Vector and therefore inherits its iteration behavior.
  • Using Stack in new code when ArrayDeque would be clearer and more modern.
  • Mutating the stack with pop() when you really wanted read-only reverse traversal.

Summary

  • 'java.util.Stack iteration follows inherited Vector order, not LIFO pop order.'
  • That behavior is surprising for stack semantics but is not a bug in the normal contract sense.
  • Use pop() for actual stack consumption order.
  • Use reverse indexing or Deque when you need top-to-bottom traversal semantics.
  • In modern Java, ArrayDeque is usually a better stack choice than Stack.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.