Stack feature imageStack feature image
HappyCoders Glasses

Stack Class in Java
(with Example)

Sven Woltmann
Sven Woltmann
Last update: June 8, 2022

Just as old as Java itself is the java.util.Stack class, available since version 1.0, implementing the abstract data type "stack".

Stack inherits from java.util.Vector and, therefore, implements numerous interfaces of the Java Collections Framework. The following diagram shows the class hierarchy:

java.util.Stack – class diagram
java.util.Stack – class diagram

Java Stack Methods

Stack extends Vector with the following methods:

  • push() – places an element on the stack
  • pop() – takes the top element from the stack
  • peek() – returns the top element of the stack without removing it from the stack
  • empty() – checks if the stack is empty; since Stack already inherits the isEmpty() method from Vector, the empty() method is redundant; why the JDK developers included it is a mystery to me.
  • search() – searches for an element on the stack and returns its distance to the top of the stack

I show how the methods work in the following example.

Just like Vector, Stack is thread-safe: all methods are synchronized.

Java Stack Example

The following code snippets show an example use of Stack (you can find the complete code in the JavaStackDemo class in the GitHub repo).

First, we create a stack and put the elements "apple", "orange", and "pear" on the stack using push():

Stack<String> stack = new Stack<>();

stack.push("pear");Code language: Java (java)

After that, we print the stack's contents – and the results of peek() and empty() – to the console:

System.out.println("stack = " + stack);

System.out.println("stack.peek() = " + stack.peek());
System.out.println("stack.empty() = " + stack.empty());Code language: Java (java)

The output looks like this:

stack = [apple, orange, pear]
stack.peek() = pear
stack.empty() = false
Code language: plaintext (plaintext)

So Stack's toString() method prints the elements from bottom to top. The last inserted element, "pear", is at the top of the stack.

Using search(), we can look for an element:

System.out.println("\"apple\") = " +"apple"));Code language: Java (java)

The output is:"apple") = 3Code language: plaintext (plaintext)

This means that "apple" is in the third position of the stack. That's because we pushed two more elements onto the stack after "apple".

We take out the three elements again:

System.out.println("stack.pop() = " + stack.pop());
System.out.println("stack.pop() = " + stack.pop());
System.out.println("stack.pop() = " + stack.pop());Code language: Java (java)

We see that the elements are retrieved in reverse order:

stack.pop() = pear
stack.pop() = orange
stack.pop() = appleCode language: plaintext (plaintext)

What happens if we call pop() one more time?

System.out.println("stack.pop() = " + stack.pop());Code language: Java (java)

As the stack is now empty, an EmptyStackException is thrown:

Exception in thread "main" java.util.EmptyStackException
	at java.base/java.util.Stack.peek(
	at java.base/java.util.Stack.pop(
	at eu.happycoders.demos.stack.JavaStackDemo.main( language: plaintext (plaintext)

Just like pop(), also peek() would throw an EmptyStackException if the stack is empty.

Why You Should Not Use Stack (Anymore)

The Java developers recommend not to use java.util.Stack anymore. The Javadoc states:

"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."

What exactly does this mean? In my opinion, Stack should not be used for the following reasons:

  1. By extending Vector, Stack provides operations that have no place in a stack, such as accessing elements by their index or inserting and deleting elements at arbitrary positions.
  2. Stack does not implement an interface. So by using Stack, you are committing to a specific implementation.
  3. Using synchronized on every method call is not a particularly performant means of making a data structure thread-safe. Better is usually optimistic locking by CAS ("compare-and-swap") operations as found in the concurrent queue and deque implementations.

Stack Alternatives

Instead, the Java developers recommend using one of the Deque implementations, such as ArrayDeque.

The java.util.Deque interface is similar to that of Stack:

  • We have the methods push(), pop(), and peek().
  • Instead of empty(), you have to call isEmpty().
  • There is no search() method.

The following code (ArrayDequeDemo in the GitHub repo) shows the exemplary application of ArrayDeque as a stack:

public class ArrayDequeDemo {
  public static void main(String[] args) {
    Deque<String> stack = new ArrayDeque<>();


    System.out.println("stack = " + stack);

    System.out.println("stack.peek() = " + stack.peek());
    System.out.println("stack.isEmpty() = " + stack.isEmpty());

    System.out.println("stack.pop() = " + stack.pop());
    System.out.println("stack.pop() = " + stack.pop());
    System.out.println("stack.pop() = " + stack.pop());

    System.out.println("stack.pop() = " + stack.pop());
Code language: Java (java)

As you can see, the code is almost identical to the previous example.

However, keep in mind that deques also provide operations that a stack should not offer, such as inserting and removing elements at the bottom of the stack.

Alternatively, you can implement your own stack class.

In the following parts of this tutorial, I will present various stack implementations:

If you still have questions, please ask them via the comment function. Do you want to be informed about new tutorials and articles? Then click here to sign up for the newsletter.