For working professionals
For fresh graduates
More
6. JDK in Java
7. C++ Vs Java
16. Java If-else
18. Loops in Java
20. For Loop in Java
46. Packages in Java
53. Java Collection
56. Generics In Java
57. Java Interfaces
60. Streams in Java
63. Thread in Java
67. Deadlock in Java
74. Applet in Java
75. Java Swing
76. Java Frameworks
78. JUnit Testing
81. Jar file in Java
82. Java Clean Code
86. Java 8 features
87. String in Java
93. HashMap in Java
98. Enum in Java
101. Hashcode in Java
105. Linked List in Java
109. Array Length in Java
111. Split in java
112. Map In Java
115. HashSet in Java
118. DateFormat in Java
121. Java List Size
122. Java APIs
128. Identifiers in Java
130. Set in Java
132. Try Catch in Java
133. Bubble Sort in Java
135. Queue in Java
142. Jagged Array in Java
144. Java String Format
145. Replace in Java
146. charAt() in Java
147. CompareTo in Java
151. parseInt in Java
153. Abstraction in Java
154. String Input in Java
156. instanceof in Java
157. Math Floor in Java
158. Selection Sort Java
159. int to char in Java
164. Deque in Java
172. Trim in Java
173. RxJava
174. Recursion in Java
175. HashSet Java
177. Square Root in Java
190. Javafx
In Java programming, managing data from both ends of a queue can be extremely useful—especially in scenarios like undo operations, palindrome checking, or implementing caching systems. That’s where the Deque (Double-Ended Queue) comes in.
A Deque allows you to insert and remove elements from both the front and the back, making it more flexible than standard queues. It is part of Java’s collection framework and is widely used in real-world applications that require efficient and dynamic data handling.
In this blog, we’ll explore what a Deque is, its key features, different implementations like ArrayDeque and LinkedList, and how to use it effectively with real Java code examples.
To better grasp these concepts and write clean, efficient code, enroll in top software engineering courses online.
Deque stands for "Double Ended Queue," which allows you to add and remove elements from both the front and the end of the queue. This flexibility makes it a powerful data structure for various algorithms and programming scenarios.
Advance your career with these proven skill-building programs.
The Deque interface provides methods for inserting, removing, and examining elements at both the head and tail of the queue:
Operation | Method | Throws Exception | Returns Special Value |
Insert | addFirst(e) | Yes | offerFirst(e) → returns boolean |
Remove | removeFirst() | Yes | pollFirst() → returns null if empty |
Examine | getFirst() | Yes | peekFirst() → returns null if empty |
Operation | Method | Throws Exception | Returns Special Value |
Insert | addLast(e) | Yes | offerLast(e) → returns boolean |
Remove | removeLast() | Yes | pollLast() → returns null if empty |
Examine | getLast() | Yes | peekLast() → returns null if empty |
Queue Method | Equivalent Deque Method |
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
Stack Method | Equivalent Deque Method |
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
Java programming provides several implementations of the Deque interface, each with its own characteristics:
1. ArrayDeque
ArrayDeque is a resizable array implementation of the Deque interface. It's the most commonly used implementation when you need a double-ended queue.
Key Features:
2. LinkedList
LinkedList implements both List and Deque interfaces, providing the capabilities of both a linked list and a double-ended queue.
Key Features:
3. ConcurrentLinkedDeque
A thread-safe variant that implements the Deque interface.
Key Features:
import java.util.ArrayDeque;
import java.util.Deque;
public class BasicDequeOperations {
public static void main(String[] args) {
// Create an ArrayDeque implementation
Deque<String> deque = new ArrayDeque<>();
// Adding elements to both ends
deque.addFirst("First");
deque.addLast("Last");
// Adding more elements
deque.offerFirst("New First");
deque.offerLast("New Last");
System.out.println("Deque contents: " + deque);
// Examining elements without removal
System.out.println("First element: " + deque.peekFirst());
System.out.println("Last element: " + deque.peekLast());
// Removing elements
System.out.println("Removed first: " + deque.removeFirst());
System.out.println("Removed last: " + deque.removeLast());
System.out.println("Updated deque: " + deque);
// Using poll methods
System.out.println("Polled first: " + deque.pollFirst());
System.out.println("Polled last: " + deque.pollLast());
System.out.println("Final deque: " + deque);
}
}
Output:
Deque contents: [New First, First, Last, New Last]
First element: New First
Last element: New Last
Removed first: New First
Removed last: New Last
Updated deque: [First, Last]
Polled first: First
Polled last: Last
Final deque: []
This example demonstrates the basic operations of adding, examining, and removing elements from both ends of a Deque using ArrayDeque implementation.
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeAsStack {
public static void main(String[] args) {
// Create a Deque to be used as a stack
Deque<Integer> stack = new ArrayDeque<>();
// Push elements onto the stack
stack.push(10);
stack.push(20);
stack.push(30);
stack.push(40);
System.out.println("Stack: " + stack);
// Peek at the top element
System.out.println("Top element: " + stack.peek());
// Pop elements from the stack
System.out.println("Popping elements:");
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}
Output:
Stack: [40, 30, 20, 10]
Top element: 40
Popping elements:
40
30
20
10
This example shows how to use a Deque as a stack with Last-In-First-Out (LIFO) behavior using push(), pop(), and peek() operations.
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeAsQueue {
public static void main(String[] args) {
// Create a Deque to be used as a queue
Deque<String> queue = new ArrayDeque<>();
// Add elements to the queue
queue.add("Customer 1");
queue.add("Customer 2");
queue.add("Customer 3");
queue.add("Customer 4");
System.out.println("Queue: " + queue);
// Peek at the first element
System.out.println("First in queue: " + queue.peek());
// Process the queue (FIFO)
System.out.println("Processing queue:");
while (!queue.isEmpty()) {
System.out.println("Serving: " + queue.remove());
}
}
}
Output:
Queue: [Customer 1, Customer 2, Customer 3, Customer 4]
First in queue: Customer 1
Processing queue:
Serving: Customer 1
Serving: Customer 2
Serving: Customer 3
Serving: Customer 4
This example demonstrates using a Deque as a regular queue with First-In-First-Out (FIFO) behavior using add(), remove(), and peek() operations.
import java.util.ArrayDeque;
import java.util.Deque;
public class PalindromeChecker {
public static boolean isPalindrome(String str) {
// Remove non-alphanumeric characters and convert to lowercase
String cleanStr = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
// Create a deque and fill it with characters
Deque<Character> deque = new ArrayDeque<>();
for (char c : cleanStr.toCharArray()) {
deque.add(c);
}
// Compare characters from both ends
while (deque.size() > 1) {
if (!deque.removeFirst().equals(deque.removeLast())) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String[] testStrings = {
"racecar",
"A man, a plan, a canal: Panama",
"hello",
"Madam, I'm Adam",
"Java"
};
for (String str : testStrings) {
System.out.println("\"" + str + "\" is a palindrome: " + isPalindrome(str));
}
}
}
Output:
"racecar" is a palindrome: true
"A man, a plan, a canal: Panama" is a palindrome: true
"hello" is a palindrome: false
"Madam, I'm Adam" is a palindrome: true
"Java" is a palindrome: false
This example demonstrates a practical application of Deque to check whether a string is a palindrome (reads the same backward as forward) by comparing characters from both ends simultaneously.
When choosing a Deque implementation, consider the performance characteristics:
Operation | ArrayDeque | LinkedList |
add/offer at head | O(1) amortized | O(1) |
add/offer at tail | O(1) amortized | O(1) |
remove/poll at head | O(1) | O(1) |
remove/poll at tail | O(1) | O(1) |
peek at head/tail | O(1) | O(1) |
Random access | O(n) | O(n) |
Memory overhead | Lower | Higher (pointers) |
Iterator traversal | Faster | Slower |
In most cases, ArrayDeque offers better performance and lower memory overhead compared to LinkedList, unless you need frequent insertions or removals in the middle of the list.
Deques are versatile data structures suitable for numerous applications:
There are multiple ways to iterate through a Deque:
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
public class DequeIteration {
public static void main(String[] args) {
Deque<String> deque = new ArrayDeque<>();
deque.add("One");
deque.add("Two");
deque.add("Three");
System.out.println("Iterating using Iterator:");
Iterator<String> iterator = deque.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("\nIterating using enhanced for loop:");
for (String element : deque) {
System.out.println(element);
}
System.out.println("\nIterating using forEach method:");
deque.forEach(System.out::println);
}
}
Output:
Iterating using Iterator:
One
Two
Three
Iterating using enhanced for loop:
One
Two
Three
Iterating using forEach method:
One
Two
Three
Standard Deque implementations like ArrayDeque and LinkedList are not thread-safe. For concurrent applications, consider:
Understanding how Deque compares to other collections helps choose the right data structure:
Feature | Deque | Queue | Stack | ArrayList | LinkedList |
Access pattern | Both ends | One end | One end | Random | Sequential/Random |
Order | Insertion | Insertion | Reverse insertion | Insertion | Insertion |
Add/remove at either end | O(1) | One end only | One end only | O(n) at front | O(1) |
Random access | No | No | No | Yes - O(1) | Yes - O(n) |
Null elements | Implementation dependent | Implementation dependent | No | Yes | Yes |
Main use cases | Multi-ended queues, sliding windows | Queuing | LIFO processing | Random access, dynamic lists | Frequent insertions/deletions |
Deque in Java provides a versatile and powerful data structure that can be used as both a stack and a queue, offering efficient operations for adding and removing elements at both ends. With multiple implementations available, you can choose the one that best fits your specific requirements for performance, memory usage, and thread safety.
By understanding what Deque in Java is, how it works, and when to use it, you can leverage this collection to solve a wide range of programming problems more efficiently. Whether you're implementing complex algorithms, managing browser history, or processing tasks in a specific order, the Deque interface provides the flexibility and performance you need.
A Queue in Java is a First-In-First-Out (FIFO) data structure where elements are added at the rear and removed from the front. A Deque (Double-Ended Queue) extends this functionality by allowing elements to be added or removed from both ends. Deque supports all Queue operations plus additional methods for working with both ends of the queue.
Use ArrayDeque for most cases as it provides better overall performance and lower memory overhead. Choose LinkedList when you need frequent insertions or removals from the middle of the list, or if you need to utilize both List and Deque functionalities. ArrayDeque doesn't allow null elements, while LinkedList does.
The standard Deque implementations (ArrayDeque, LinkedList) are not thread-safe. For thread-safe operations, use ConcurrentLinkedDeque, or wrap a Deque implementation with Collections.synchronizedDeque(). Always consider the performance implications of synchronized collections in high-concurrency environments.
Yes, all standard Deque implementations in Java allow duplicate elements. Elements are ordered based on insertion order, not by their values.
Using ArrayDeque as a stack is generally faster than using java.util.Stack. The Stack class extends Vector, which is synchronized and has performance overhead. ArrayDeque provides better performance for stack operations and is the recommended approach since Java 6.
Calling removeFirst() on an empty Deque throws a NoSuchElementException. If you want to avoid exceptions, use pollFirst() instead, which returns null when the Deque is empty.
Deque is not designed for priority-based ordering. For priority queue functionality, use the PriorityQueue class or PriorityBlockingQueue for thread-safe operations.
You can convert a Deque to an array using the toArray() method:
Deque<String> deque = new ArrayDeque<>();
// Add elements...
String[] array = deque.toArray(new String[0]);
Deque doesn't provide direct sorting methods. To sort elements, you can convert the Deque to a List, sort the List, and then create a new Deque from the sorted List:
Deque<Integer> deque = new ArrayDeque<>();
// Add elements...
List<Integer> list = new ArrayList<>(deque);
Collections.sort(list);
deque = new ArrayDeque<>(list);
ArrayDeque starts with an initial capacity (16 by default) and automatically resizes when needed. The capacity is always a power of 2, which optimizes array-based operations. LinkedList doesn't have capacity constraints as it uses linked nodes.
Standard Deque implementations don't support fixed size directly. You can create wrapper classes to enforce size limits, or use specialized implementations like CircularFifoQueue from Apache Commons Collections.
Take the Free Quiz on Java
Answer quick questions and assess your Java knowledge
Author|900 articles published
Previous
Next
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918068792934
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.