24

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()); }
durron597
  • 31,968
  • 17
  • 99
  • 158

2 Answers2

21

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.

fvu
  • 32,488
  • 6
  • 61
  • 79
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.

Amit
  • 797
  • 9
  • 32
  • 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? – Clockwork-Muse Feb 15 '13 at 18:27