Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
The Stack Class in Java is part of the java.util package and represents a last-in, first-out (LIFO) data structure. It extends the Vector class and provides methods like push(), pop(), and peek() for element operations. Stack in Java is commonly used in algorithms like expression evaluation, backtracking, and undo functionality. The Stack class offers both flexibility and simplicity when handling data in a LIFO manner.
What is the Collection Framework in Java?
A single unit of objects in Java is referred to as a collection. A collection is a framework that allows us to store and modify a group of objects. Java Collections can perform various data operations, including searching, sorting, insertion, manipulation, and deletion.
JDK 1.2 introduced the collection framework. It is present in the Java.util.Collectionpackage. It contains three sections as given below:
Interfaces: Interfaces are designed to allow the manipulation of collections independently. The Java hierarchy consists of six core collection interfaces. They are Collection, Set, List, SortedSet, Map and SortedMap.
Implementations: It contains the implementations of the collection interfaces. They are blueprints of data structures. For example, stack linked lists.
Algorithms: Algorithms contain functions designed to make collections easy to use and implement. For example, searching, sorting, insertion, deletion etc.
What is the Stack Class in Java?
The Stack class is based on the principle of Last in First out (LIFO). The element inserted last will be the first to be removed. The Stack class provided by Java Collections implements five interfaces. The list of those interfaces is given below:
Serializable: This interface allows classes to be serialized and deserialized.
Cloneable: This interface allows a class to clone its objects.
RandomAccess: This interface is used by sequential or List implementations to support fast random access(constant time).
Iterable<E>: This interface represents a collection of objects which can be iterated.
Collection<E>: This is the root interface in the collection hierarchy. It represents a group of objects, known as its elements.
List<E>: It is a child of the Collection interface. It provides a way to store the ordered elements.
Hierarchy of the Stack class
The Stack class in Java is part of the java.util package and extends the Vector class, following a specific inheritance hierarchy. This hierarchy helps the Stack class inherit useful features like dynamic resizing and collection handling. Here's the structure explained from top to bottom:
Object
The root class of the Java class hierarchy. All classes in Java inherit from Object.
AbstractCollection
Provides a basic implementation of the Collection interface, reducing the effort to implement it from scratch.
AbstractList
Extends AbstractCollection and provides a skeletal implementation of the List interface.
Vector
A resizable-array implementation of the List interface. It’s synchronized and thread-safe.
Stack
Inherits all features of Vector and adds LIFO (Last-In-First-Out) operations like push(), pop(), peek(), and search().
This structure means the Stack class gets all the functionalities of a list and vector while adding its unique stack-specific behaviors, making it useful for managing data where Stack in Java is required, such as parsing, expression evaluation, and recursion tracking.
The constructor of Stack Class
The Stack class in Java contains only one constructor. It creates an empty Stack.
Constructor: Stack()
Creating a Stack in Java
A Stack can be created in Java using the above constructor.
Syntax:
Stack<Type> name_of_stack = new Stack<Type>();
Here, type specifies the type of object such as Integer, String and Float etc.
Example
Stack<Integer> stack1 = new Stack<Integer>();
Stack<String> stack2 = new Stack<String>();
//stack1, stack2 represents name of the stack created
Note: Stack can be initialized without any type as well. Such classes can store any object.
Stack stack1 = new Stack();
//stack1 represents name of the stack created
Methods of Stack Class
This built-in Stack in Java also contains predefined methods. Some of the important methods are given below:
push(datatype element): This method pushes the element onto the top of the stack.
pop(): This method removes the element at the top of the stack. It returns that element as the value.
peek(): It returns the object at the top of the stack without removing it.
empty(): It checks if the stack is empty.
search(Object obj): This function returns the 1-based position where an object is on the stack.
Note: Stack class extends Vectorclass. Stack class includes all the methods defined by the Vector class and adds several of its own.
Some of the important methods inherited from the class java.util.Vector are:
Image credits: Java: The Complete Reference By Herbert Schildt
Stack Class push() Method
The push() method is used to add an item to the top of the stack. This method takes a single argument, which is the item to be pushed onto the stack. After the call, the new item becomes the top element of the stack.
Example:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println("Stack after pushes: " + stack); // Output: [10, 20, 30]
}
}
Stack Class pop() Method
The pop() method is used to remove the item at the top of the stack and return it. This method modifies the stack by removing the top element. If the stack is empty when pop() is called, it throws an EmptyStackException.
Example:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
int topElement = stack.pop();
System.out.println("Popped element: " + topElement); // Output: 30
System.out.println("Stack after pop: " + stack); // Output: [10, 20]
}
}
Stack Class peek() Method
The peek() method returns the item at the top of the stack without removing it. This method provides a way to look at the top element without modifying the stack. If the stack is empty when peek() is called, it throws an EmptyStackException.
Example:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
int topElement = stack.peek();
System.out.println("Top element: " + topElement); // Output: 30
System.out.println("Stack after peek: " + stack); // Output: [10, 20, 30]
}
}
Stack Class empty() Method
The empty() method checks whether the stack is empty or not. It returns true if the stack contains no elements, and false otherwise.
Example:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
System.out.println("Is stack empty? " + stack.empty()); // Output: true
stack.push(10);
System.out.println("Is stack empty? " + stack.empty()); // Output: false
}
}
Stack Class search() Method
The search() method searches for an item in the stack and returns the 1-based position from the top of the stack. If the item is found, it returns the distance from the top of the stack. If the item is not found, it returns -1.
Example:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
int position = stack.search(20);
System.out.println("Position of 20: " + position); // Output: 2
position = stack.search(40);
System.out.println("Position of 40: " + position); // Output: -1
}
}
Now, let’s see the implementation of Stack in Java.
Implementation
Java
Java
import java.util.*;
public class DemoStack { static void showpush(Stack<Integer> st, int a) { st.push(a); System.out.println("push(" + a + ")"); System.out.println("stack: " + st); }
The time complexity of push(), pop(), peek(), isEmpty(), isFull() and size() is constant, i.e., O(1).
Check out this video for more concepts about Stack data structure.
Prioritize the use of Deque over Stack
In Java, while the Stack class has traditionally been used for stack operations, it's generally recommended to use the Deque interface (short for "double-ended queue") over Stack for several reasons. Here’s an explanation of why Deque is preferred and how it can be used for stack operations:
Why Use Deque over Stack?
1. Inheritance and Design:
The Stack class extends Vector, which is synchronized and thread-safe. This can lead to unnecessary overhead if thread safety is not required.
Deque is a more general-purpose interface that is designed for both stack (LIFO) and queue (FIFO) operations, providing more flexibility.
2. API and Functionality:
Deque provides a richer set of methods for stack operations compared to Stack. Methods like addFirst(), removeFirst(), peekFirst(), etc., can be used to implement stack-like behavior.
Deque also supports operations at both ends, which Stack does not, making Deque more versatile.
3. Performance:
The implementations of Deque (like ArrayDeque and LinkedList) are generally more efficient than Stack for stack operations because they do not have the synchronization overhead of Vector.
4. Best Practices:
The Java Collections Framework has evolved, and modern best practices favor the use of interfaces over concrete classes. Using Deque aligns with this practice and provides better abstraction.
Legacy Classes in Java
As we’ve seen above, legacy classes were included in Java from the initial versions. But when Collections were introduced, they were on the verge of depreciation. To make them compatible, Java restructured those classes. They are not obsolete, but their better alternatives are present in Java.
For example, the Deque interface and its implementations provide a more comprehensive and consistent set of LIFO stack operations. Therefore they should be used instead of Stack class.
To learn in more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples, you can refer to the official documentation of Java here.
Stack vs. Queue in Java
Stacks and Queues are linear data structures with different access methods. A Stack follows LIFO (Last-In-First-Out), meaning the last element added is the first to be removed. A Queue follows FIFO (First-In-First-Out), where the first element added is the first to be removed.
Differences in Structure and Use Cases
Feature
Stack
Queue
Order
LIFO
FIFO
Insertion
push() at top
add() at rear
Removal
pop() from top
remove() from front
Use Cases
Undo operations, backtracking
Task scheduling, buffering
Access Pattern
One end (top) only
Both ends (front and rear)
Code Comparison
// Stack Example
Stack<Integer> stack = new Stack<>();
stack.push(10); // Push element
stack.push(20);
int top = stack.pop(); // Pop element
System.out.println("Stack Top: " + top);
// Queue Example
Queue<Integer> queue = new LinkedList<>();
queue.add(10); // Add element
queue.add(20);
int front = queue.remove(); // Remove element
System.out.println("Queue Front: " + front);
Both structures offer simple APIs, but they manage data in different orders suited for different problems.
Advantages of the Stack Class in Java
1. Built-in Functionality
Java provides the Stack class in the java.util package, which means developers don't need to implement stack logic from scratch. This built-in support simplifies coding and ensures reliability through tested standard methods.
2. Standardized LIFO Operations
The Stack class supports intuitive and standardized LIFO methods like push(), pop(), and peek(). These operations follow a consistent pattern and allow developers to work with stack data without dealing with index-level access.
3. Integration with Java Collections Framework
As Stack extends the Vector class, it inherits many useful methods. It integrates well with other parts of the Java Collections Framework, such as iteration with iterators and access to synchronized methods.
4. Thread Safety
The Stack class is synchronized, making it safer for use in multi-threaded environments. It ensures that only one thread can access the stack at a time, which is useful in concurrent applications.
5. Useful for Common Use Cases
Stack is ideal for solving problems such as undo/redo functionality, expression parsing, backtracking in algorithms, and recursive function emulation, making it a handy structure in many programming scenarios.
Limitations of the Stack Class in Java
While Java’s Stack class is functional and easy to use, it suffers from performance and design limitations that make it less favorable in modern Java applications.
Thread Safety Overhead
Since Stack is synchronized by default (due to extending Vector), every operation incurs thread safety checks. This introduces unnecessary performance overhead in single-threaded environments, where synchronization is not needed. Thus, it’s not the best fit for performance-critical applications unless thread safety is explicitly required.
Better Alternatives: Deque (ArrayDeque)
For LIFO stack operations, ArrayDeque from the Deque interface is typically recommended. It provides faster and more efficient performance, as it is not synchronized and avoids the legacy design overhead of Stack. It also supports all stack operations like push(), pop(), and peek() in a modern and optimized structure.
Frequently Asked Questions
What is stack in collection in Java?
A stack in Java is a data structure that follows the Last-In-First-Out (LIFO) principle for adding and removing elements.
When to use stack in Java?
Use a stack in Java for algorithms requiring LIFO behavior, such as depth-first search, expression evaluation, and backtracking.
How to take stack in Java?
Use java.util.Stack class or prefer Deque implementations like ArrayDeque for stack operations, offering push, pop, and peek methods.
What is the stack size in Java collection?
The size of a stack in Java collections is dynamically managed, limited only by available memory.
Conclusion
The Stack Class in Java offers an efficient way to handle data using the LIFO principle. It extends Vector and provides useful methods like push(), pop(), and peek(). This article covered its features, hierarchy, and usage, helping you understand how the Stack in Java works in real-world coding scenarios.