Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing stack to console while popping elements throws exception non-deterministically

I was just writing a remarkably simply "Stack" class in Java on the eclipse Juno IDE that has 2 operations - push and pop. One check I have in the pop() method is to see if the stack is empty; if so, I throw a NoSuchElementException. Therefore, if I push 1,2,3,4,5 sequentially and then pop elements five times, I expect to see 5,4,3,2,1 printed out in that order. But after adding five elements, if i deliberately try to pop the stack SIX times, I would expect 5,4,3,2,1, and then a NoSuchElementException.

What's happening in my case is that console prints out the NoSuchElementException haphazardly (i.e. not always after printing out 5,4,3,2,1; sometimes it prints out:

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 it prints out:

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 governs this behavior. Since I'm using print statements (and not a logger which might have a queue-like implementation underneath) I would expect to see the statements in order, but I suspect that there's some concurrency at play 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 out and more importantly, what could be causing this non-deterministic printing of the exception in the console?

like image 445
BSJ Avatar asked Mar 23 '23 16:03

BSJ


1 Answers

this is because the System.err and the System.out are not the same stream, sometimes can happen that they are not synchronized. System.err is for exception, System.out is what you use.

maybe you want to try something like this:

System.setErr(System.out);

Thiw will route the standard System.err to the System.out now you should have the correct 5,4,3,2,1, Exception flow.

Obviously if the two stream are separated there is a reason, so you can do what I told you but be careful to do it just during testing (like in jUnit)

like image 136
Gianmarco Avatar answered Apr 06 '23 03:04

Gianmarco