DevNotes
Support
Collection Framework · Chapter 11

Queue Interface

FIFO processing, the three method pairs (add/offer, remove/poll, element/peek), implementations and BlockingQueue.

◷ 10 min read§ 15 sections? 16 interview questions{ } 18 code examples

#Introduction

Queue is one of the core Collection interfaces and is heavily used in multithreading, messaging, task processing, BFS, scheduling and producer-consumer systems.

The most important thing to understand is:

Queue normally follows FIFO — First In, First Out — but not every Queue implementation guarantees FIFO ordering.

That exception becomes important when we study PriorityQueue.

#What is Queue?

Queue represents a collection designed primarily for holding elements before they are processed.

Package:

Java
java.util.Queue
  • Iterable
    • Collection
      • Queue
        • LinkedList
        • PriorityQueue
        • ArrayDeque
Hierarchy

Some concurrent implementations (covered later) include BlockingQueue, ArrayBlockingQueue, LinkedBlockingQueue and PriorityBlockingQueue.

#FIFO Principle

The typical Queue behaviour is First In, First Out.

10head
20
30
40tail
head ← … ← tail

Remove → 10 comes out. Then the queue is 20 → 30 → 40. This is similar to a real-world queue at a counter.

Queue Does NOT Always Mean FIFO

This is an important interview nuance. A normal FIFO Queue processes elements in insertion order, but implementations can use different ordering policies. For example, PriorityQueue orders elements according to their priority/natural ordering rather than insertion order.

#Core Queue Methods

Queue has three important method pairs. This is extremely important for interviews.

OperationThrows exceptionReturns special value
Insertadd(e)offer(e)
Removeremove()poll()
Inspectelement()peek()

Easy memory trick: add ↔ offer, remove ↔ poll, element ↔ peek. The right-hand methods are generally safer when you want to handle failure without exceptions.

add() vs offer()

Both attempt to insert an element:

Java
queue.add(10);
queue.offer(10);

The difference appears when insertion cannot be performed:

MethodFailure behaviour
add()Throws exception
offer()Returns false

For an unbounded Queue such as LinkedList or ArrayDeque, capacity failure normally isn't an issue. The distinction becomes especially useful with bounded queues.

remove() vs poll()

Both remove the head. If the Queue is empty:

MethodEmpty queue
remove()NoSuchElementException
poll()null

element() vs peek()

Both inspect the head without removing it. If empty:

MethodEmpty queue
element()NoSuchElementException
peek()null

Basic Example

Java
Queue<String> queue = new LinkedList<>();

queue.offer("A");
queue.offer("B");
queue.offer("C");

System.out.println(queue.poll());
System.out.println(queue.peek());
Output
A
B

After poll() the queue is B → C.

Queue Does Not Provide Index-Based Access

Unlike List, Queue doesn't provide get(index). Why? Because Queue focuses on inserting, removing the head and inspecting the head — rather than positional access.

#Queue Implementations

The important implementations for interviews are LinkedList, PriorityQueue and ArrayDeque (and later, BlockingQueue implementations).

LinkedList as Queue

Since LinkedList implements Queue:

Java
Queue<Integer> queue = new LinkedList<>();

You can use offer(), poll() and peek(). Internally, LinkedList can efficiently add/remove at its ends.

ArrayDeque as Queue

ArrayDeque is usually a better general-purpose Queue than LinkedList.

Java
Queue<Integer> queue = new ArrayDeque<>();

Advantages:

  • Array-based
  • Efficient
  • No node allocation per element
  • Good cache locality
  • No synchronization overhead

For ordinary single-threaded FIFO queues, ArrayDeque is often the preferred choice.

ArrayDeque vs LinkedList

FeatureArrayDequeLinkedList
Internal structureResizable array/dequeDoubly linked list
Queue operationsEfficientEfficient
Memory overheadLowerHigher
Cache localityBetterWorse
Null elements❌ Not allowed✅ Allowed
Typical choicePreferredUseful when List behaviour is also needed

PriorityQueue

PriorityQueue is where many candidates make a mistake. It is a Queue, but it is not FIFO.

Java
Queue<Integer> queue = new PriorityQueue<>();

queue.offer(30);
queue.offer(10);
queue.offer(20);

The head is 10, because the smallest element has the highest priority under natural ordering.

PriorityQueue uses a binary heap — by default a min-heap:

  • 10
    • 30
    • 20
The smallest element is at the head

We'll cover PriorityQueue in detail in its own chapter.

Queue Ordering Comparison

ImplementationOrdering
LinkedListFIFO
ArrayDequeFIFO
PriorityQueuePriority
BlockingQueue variantsDepends on implementation

Queue with Custom Objects

Java
class Task {
    int priority;
    String name;
}

A priority-based Queue can use:

Java
Queue<Task> tasks = new PriorityQueue<>(Comparator.comparingInt(t -> t.priority));

Now tasks are processed according to the comparator. This is a common real-world pattern.

#Queue Use Cases

Queue is ideal when work must be processed progressively.

Task processing
Request 1 · Request 2 · Request 3
Queue
Worker
Messaging
Producer
Queue
Consumer
BFS
Start
Queue
Process level by level
Request buffering
Incoming Requests
Queue
Workers

Producer-Consumer Pattern

A classic interview scenario: Producer → Queue → Consumer.

Java
// Producer
queue.offer(task);

// Consumer
Task task = queue.poll();

#BlockingQueue

BlockingQueue is part of java.util.concurrent. It extends Queue and adds blocking behaviour.

Java
BlockingQueue<Task> queue = new ArrayBlockingQueue<>(100);
Java
// Producer
queue.put(task);

// Consumer
Task task = queue.take();
SituationBehaviour
Queue is fullput() waits
Queue is emptytake() waits

This makes BlockingQueue particularly useful for producer-consumer architectures.

Method Families in Concurrent Queues

With bounded queues, the method choice becomes especially meaningful:

InsertBehaviourRemoveBehaviour
add()Exception on failureremove()Exception
offer()false on failurepoll()null
put()Waitstake()Waits
offer(e, timeout)Waits up to timeoutpoll(timeout)Waits up to timeout

This distinction is very useful in concurrency interviews.

#Queue vs Stack vs Deque vs List

Queue vs Stack

Interview favourite.

Queue — FIFO
10 → 20 → 30
remove() → 10
Stack — LIFO
30top
20
10
pop() → 30

Modern Java generally uses Deque for stack behaviour rather than the legacy Stack class.

Queue vs Deque

Queue normally focuses on inserting at the tail and removing from the head. Deque supports both ends (front and rear), so it can behave as a Queue + Stack.

Java
Deque<Integer> deque = new ArrayDeque<>();

// Queue
deque.offerLast(10);
deque.pollFirst();

// Stack
deque.push(10);
deque.pop();

Queue vs List

FeatureQueueList
Primary purposeProcessing orderOrdered collection
Index access❌ No✅ get(index)
Head operationsCore functionalityNot the focus
FIFO semanticsCommonNo

#Null Elements and Programming to the Interface

Null Elements

This depends on the implementation:

ImplementationNull allowed?
LinkedList✅ Yes
ArrayDeque❌ No
PriorityQueue❌ No
Java
Queue<String> q = new LinkedList<>();
q.offer(null);   // allowed

Important reason: for methods such as poll() and peek(), null is used to indicate that the queue is empty.

Queue is an Interface

Prefer programming to the interface:

Java
Queue<Task> queue = new ArrayDeque<>();

rather than:

Java
ArrayDeque<Task> queue = new ArrayDeque<>();

unless you specifically need ArrayDeque-only operations. This makes the implementation easier to replace.

#Time Complexity

OperationArrayDequeLinkedListPriorityQueue
offerO(1) amortizedO(1)O(log n)
pollO(1)O(1)O(log n)
peekO(1)O(1)O(1)
containsO(n)O(n)O(n)

PriorityQueue has O(log n) insertion/removal because the heap may need reordering.

#Common Mistakes

  • "Queue always means FIFO." Not universally — PriorityQueue uses priority ordering.
  • Using remove() without considering an empty Queue. Safer alternative: queue.poll() when null is an acceptable empty indication.
  • Using LinkedList as the default Queue. For a normal single-threaded Queue, ArrayDeque is generally a better choice.
  • Using ArrayDeque for a multi-threaded producer-consumer system. It is not thread-safe — use an appropriate concurrent Queue, commonly a BlockingQueue.
  • Using PriorityQueue when you need insertion order. PriorityQueue does not preserve FIFO ordering.

#Interview Scenarios

Q1Single-threaded FIFO task processing

Best choice:

Java
Queue<Task> queue = new ArrayDeque<>();

FIFO + efficient + low memory overhead + no synchronization needed.

Q2Multiple producers and consumers

The queue should wait when it is full (producer waits) or empty (consumer waits). Use a BlockingQueue<Task>, for example:

Java
BlockingQueue<Task> queue = new ArrayBlockingQueue<>(100);
Q3Repeatedly process the smallest value

Use PriorityQueue<Integer>, because it provides priority ordering.

Q4Quick interview test
Java
Queue<Integer> q = new ArrayDeque<>();

q.offer(10);
q.offer(20);
q.offer(30);

System.out.println(q.peek());
System.out.println(q.poll());
System.out.println(q.peek());
Output
10
10
20

Because offer adds at the tail, peek inspects the head, and poll removes the head.

#Frequently Asked Interview Questions

Q1What is Queue?

A Collection designed primarily for holding elements before processing, usually with FIFO semantics.

Q2What is FIFO?

First In, First Out.

Q3Difference between add() and offer()?
  • add() → exception if insertion fails
  • offer() → false if insertion fails
Q4Difference between remove() and poll()?
  • remove() → exception if empty
  • poll() → null if empty
Q5Difference between element() and peek()?
  • element() → exception if empty
  • peek() → null if empty
Q6Is PriorityQueue FIFO?

No. It orders elements according to priority.

Q7Which Queue implementation is generally preferred for ordinary FIFO behaviour?

ArrayDeque.

Q8Is LinkedList a Queue?

Yes. It implements Deque, which extends Queue.

Q9Is ArrayDeque thread-safe?

No.

Q10Which Queue should you use for producer-consumer communication?

Usually an appropriate BlockingQueue, depending on the requirements.

Q11Can Queue contain null?

Depends on the implementation. LinkedList allows it; ArrayDeque and PriorityQueue do not.

Q12What is the difference between Queue and Deque?

Queue primarily models one-ended insertion/removal behaviour, while Deque supports insertion and removal at both ends.

#Decision Framework

Need a Queue?
Concurrent producer/consumer with blocking?
BlockingQueue
continue
Normal FIFO?
ArrayDeque
PriorityQueue

Final Mental Model

  • Queue
    • ArrayDequeFIFO · fast
    • LinkedListFIFO · flexible
    • PriorityQueuePriority · heap

For modern Java:

NeedUse
Normal queueArrayDeque
Concurrent producer/consumerBlockingQueue
Priority processingPriorityQueue

#Chapter Summary

ConceptKey Point
QueueHolds elements for processing
Typical behaviourFIFO
add()Insert, exception on failure
offer()Insert, special-value failure
remove()Remove head, exception if empty
poll()Remove head, null if empty
element()Inspect head, exception if empty
peek()Inspect head, null if empty
ArrayDequePreferred general-purpose FIFO Queue
LinkedListQueue + Deque + List
PriorityQueuePriority ordering
BlockingQueueConcurrent producer-consumer use
Thread-safe?Depends on implementation

Interview Readiness Checklist

  • What is Queue?
  • What does FIFO mean?
  • Why doesn't PriorityQueue follow FIFO?
  • add() vs offer()?
  • remove() vs poll()?
  • element() vs peek()?
  • ArrayDeque vs LinkedList?
  • Queue vs Deque?
  • Queue vs Stack?
  • Why is ArrayDeque preferred over LinkedList for ordinary queues?
  • Why can't ArrayDeque contain null?
  • What is BlockingQueue?
  • Which collection would you use for producer-consumer architecture?
  • Which collection would you use for priority-based processing?