
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 Stack Methods
Stack extends Vector with the following methods:
push()– places an element on the stackpop()– takes the top element from the stackpeek()– returns the top element of the stack without removing it from the stackempty()– checks if the stack is empty; sinceStackalready inherits theisEmpty()method fromVector, theempty()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("apple");
stack.push("orange");
stack.push("pear");
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());
The output looks like this:
stack = [apple, orange, pear]
stack.peek() = pear
stack.empty() = false
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("stack.search(\"apple\") = " + stack.search("apple"));
The output is:
stack.search("apple") = 3
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());
We see that the elements are retrieved in reverse order:
stack.pop() = pear
stack.pop() = orange
stack.pop() = apple
What happens if we call pop() one more time?
System.out.println("stack.pop() = " + stack.pop());
As the stack is now empty, an EmptyStackException is thrown:
Exception in thread "main" java.util.EmptyStackException
at java.base/java.util.Stack.peek(Stack.java:101)
at java.base/java.util.Stack.pop(Stack.java:83)
at eu.happycoders.demos.stack.JavaStackDemo.main(JavaStackDemo.java:28)
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:
- By extending
Vector,Stackprovides operations that have no place in a stack, such as accessing elements by their index or inserting and deleting elements at arbitrary positions. Stackdoes not implement an interface. So by usingStack, you are committing to a specific implementation.- Using
synchronizedon 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(), andpeek(). - Instead of
empty(), you have to callisEmpty(). - 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<>();
stack.push("apple");
stack.push("orange");
stack.push("pear");
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());
}
}
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:
- using an ArrayDeque
- using an Array
- using a LinkedList
- using Queues
Did this article save you time? Then I’d be happy if you invested a minute of it in a review on my ProvenExpert profile. Your feedback shows me that the work on these articles pays off.
Would you like to be notified by email when I publish a new article? Then click here to join the HappyCoders newsletter.




