25

When using Java's foreach syntax, Stack doesn't use LIFO ordering on the outputted elements. Consider the following code:

import java.util.Queue;
import java.util.Stack;
import java.util.LinkedList;

public class QueueStackTest {
  private static int[] numbers = {1, 2, 3, 4, 5};

  public static void main(String[] args) {
    Stack<Integer> s = new Stack<Integer>();
    Queue<Integer> l = new LinkedList<Integer>();

    for (int i : numbers) {
      s.push(i);
      l.offer(i);
    }

    System.out.println("Stack: ");
    for(Integer i : s) {
      System.out.println(i);
    }

    System.out.println();
    System.out.println("Queue:");
    for(Integer i : l) {
      System.out.println(i);
    }
  }
}

Output:

Stack: 
1
2
3
4
5

Queue:
1
2
3
4
5

Questions:

  1. Does this make sense? Is it a bug?
  2. Can I guarantee that this will, at least, return Queue elements in the correct order?
  3. When consuming (processing) a Stack or a Queue, is this the best way to do it? Or should I make a more manual loop with something like: while(!s.isEmpty()) { handle(s.pop()); } or while(!l.isEmpty()) { handle(l.poll()); }
1
  • Have you tried using just a normal for loop? Commented Feb 15, 2013 at 18:10

2 Answers 2

22

There is an interesting footnote in Stack's Javadoc:

A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class. For example:

Deque stack = new ArrayDeque();

An extended version of your program:

  public static void main(String[] args) {
    Stack<Integer> s = new Stack<Integer>();
    Deque<Integer> d = new ArrayDeque<Integer>();
    Queue<Integer> l = new LinkedList<Integer>();

    for (int i : numbers) {
      s.push(i);
      l.offer(i);
      d.push(i);
    }

    System.out.println("Stack: ");
    for(Integer i : s) {
      System.out.println(i);
    }

    System.out.println();
    System.out.println("Queue:");
    for(Integer i : l) {
      System.out.println(i);
    }
    System.out.println();
    System.out.println("Deque:");
    for(Integer i : d) {
      System.out.println(i);
    }
  }   

gives

....
Deque:
5
4
3
2
1

So maybe switch to Deque for a more consistent behavior.

1
  • This is a far better answer than the other one. +1
    – durron597
    Commented Feb 15, 2013 at 18:34
15

You need to use pop() & poll() instead of for loop. Thats the API offered by Stack/Queue.

When you iterate, you are directly iterating the internal representation of Stack/Queue.

1
  • Perhaps you could go into the reason why pop() can't be used. For example, what happens in other collections if an element is removed? And 'iterating the internal representation' is slightly misleading (as a bound-size queue is probably 'circular') - what is the iterator really returning? Commented Feb 15, 2013 at 18:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.