I just wrote a remarkably simple "Stack" class in Java on the eclipse Juno IDE, which has 2 operations - push and pop. One check I have in the pop () method is to see if it is empty; if so, I throw a NoSuchElementException. Therefore, if I click 1,2,3,4,5 sequentially, and then pop the elements five times, I expect to see 5,4,3,2,1 printed in that order. But after adding five elements, if I intentionally try to push the stack in SIX times, I would expect 5,4,3,2,1 and then a NoSuchElementException.
What happens in my case is that the console unexpectedly throws a NoSuchElementException (i.e. not always after printing 5,4,3,2,1, sometimes it prints:
stack pop: 5 stack pop: 4 Exception in thread "main" java.util.NoSuchElementException: Stack Underflow stack pop: 3 stack pop: 2 stack pop: 1 at Stack.pop(Stack.java:29) at Stack.main(Stack.java:47)
and sometimes he prints:
Exception in thread "main" stack pop: 5 stack pop: 4 stack pop: 3 stack pop: 2 stack pop: 1 java.util.NoSuchElementException: Stack Underflow at Stack.pop(Stack.java:29) at Stack.main(Stack.java:47)
My goal is to understand what regulates this behavior. Since I use print statements (and not a log, which may have a similar implementation queue under it), I would expect the instructions to be fine, but I suspect there is something concurrency here. Below is my code:
import java.util.NoSuchElementException;
public class Stack { private Node first; private int size; private class Node{ Node next; int value; } public Stack(){ size=0; first=null; } public void push(int x){ Node previousFirst = first; first = new Node(); first.value = x; first.next = previousFirst; size++; } public int pop(){ if(first == null){ throw new NoSuchElementException("Stack Underflow"); } int poppedNodeVal = first.value; first = first.next; size--; return poppedNodeVal; } public static void main(String[] args) { Stack stack1 = new Stack(); stack1.push(1); stack1.push(2); stack1.push(3); stack1.push(4); stack1.push(5); for(int i=5; i>=0;i--){ System.out.println("stack pop: " + stack1.pop()); } } }
Any thoughts on how to reliably print this and, more importantly, what could cause this non-deterministic exception printing in the console?