Detailed explanation
In Java, Queue<E> represents a collection designed to hold elements before processing, while Deque<E> extends Queue<E> and adds explicit operations at both ends. A typical queue follows FIFO: elements are inserted at the tail and removed from the head. Therefore, saying that queue insertion and removal happen “at one end” is misleading. Also, FIFO is not guaranteed by every Queue implementation: PriorityQueue selects elements according to natural ordering or a comparator rather than insertion order.
Queue provides two groups of methods for its core operations. add(e), remove(), and element() throw exceptions when insertion fails because of capacity restrictions or when the queue is empty, as applicable. Their alternatives offer(e), poll(), and peek() report these conditions using false or null. poll() removes the head, whereas peek() only examines it. Deque adds paired methods such as offerFirst(e)/offerLast(e), pollFirst()/pollLast(), and peekFirst()/peekLast(), making the chosen end explicit. The interface defines the available operations, while the implementation determines storage, performance, capacity limits, and thread safety.
When a Deque is used as a FIFO queue, offer(e) is equivalent to offerLast(e), while poll() and peek() correspond to pollFirst() and peekFirst(). It can also behave as a LIFO stack: push(e) inserts at the front, pop() removes from the front, and peek() examines that front element. For example, with Deque<Integer> stack = new ArrayDeque<>(), pushing 1 and then 2 makes pop() return 2. Unlike poll(), pop() throws NoSuchElementException when the deque is empty. Deque is generally preferred over the legacy Stack class for stack-style code.
ArrayDeque is a common implementation backed by a resizable array, with most end operations taking amortized constant time; resizing occasionally requires copying elements. It rejects null and is not thread-safe. LinkedList also implements Deque, using linked nodes instead of an array. In interviews, explain the interface relationship, operation mapping, and FIFO-versus-LIFO use cases before discussing implementations. Choose Queue when callers need only queue operations, and Deque when the code needs both ends or stack operations; concurrent access requires an appropriate concurrent implementation or external synchronisation.
Key points to remember
- Deque extends Queue and supports insertion, removal, and inspection at both ends.
- Typical FIFO queues insert at the tail and remove from the head; PriorityQueue uses priority ordering instead.
- offer, poll, and peek return special values for capacity failure or emptiness; add, remove, and element throw exceptions for those conditions.
- On a Deque, offer maps to offerLast, poll to pollFirst, and peek to peekFirst.
- ArrayDeque supports efficient queue and stack usage, rejects null, and is not thread-safe.
Common mistakes candidates make
- Saying that FIFO queues insert and remove at the same end, or that every Queue implementation guarantees FIFO.
- Confusing peek with removal, or assuming pop returns null when the deque is empty.
- Assuming all Deque implementations share the same null policy, storage model, or thread-safety guarantees.
Likely follow-up questions
Why is Deque preferred over Stack in Java?
Deque provides a consistent API for LIFO operations without the legacy Vector inheritance of Stack. ArrayDeque is a common choice for single-threaded stack usage, but it does not provide Stack's synchronised methods.
Can a Deque be assigned to a Queue reference?
Yes, because Deque extends Queue: Queue<Integer> queue = new ArrayDeque<>(); is valid. Through that reference, only Queue operations and its inherited methods are available, not Deque-specific methods such as offerFirst or push.
Which implementation should you use for concurrent access?
ConcurrentLinkedDeque supports thread-safe, non-blocking operations at both ends. LinkedBlockingDeque supports blocking operations and can be bounded, making it useful when producers or consumers need to wait for space or elements.
Interview tip: Start with the interface relationship, explain the head-and-tail operations, and demonstrate FIFO versus LIFO with two elements.
