Back to Blog
Java

Java LinkedList as Queue: Implementation and Tradeoffs

java linkedlist as queue: Learn how to use Java's LinkedList as a Queue, its FIFO behavior, methods, and when it's a better choice than ArrayDeque.

JavaLinkedListQueueData StructuresCollectionsFIFO
Diagram showing a LinkedList used as a queue with elements entering at tail and leaving at head.

java linkedlist as queue requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

Using a Java LinkedList as a queue is a common pattern because LinkedList implements the Queue interface directly. You can assign a LinkedList instance to a Queue reference and use it as a FIFO queue. The Queue interface defines methods like offer, poll, and peek, which LinkedList provides with expected semantics.

Queue<String> queue = new LinkedList<>(); queue.offer("first"); queue.offer("second"); queue.offer("third"); String head = queue.poll(); // "first" String peeked = queue.peek(); // "second"

The offer method adds an element at the tail, poll removes and returns the head, and peek returns the head without removing it. This is the standard queue contract.

Queue Operations: offer, poll, and peek

The Queue interface has two sets of methods: one that returns null or false on failure, and another that throws exceptions. LinkedList implements both. The table below summarizes the methods:

OperationReturns null/falseThrows exception
Addoffer(e)add(e)
Removepoll()remove()
Examinepeek()element()

For a LinkedList, offer always succeeds because the list is unbounded, so add and offer behave identically. Similarly, poll and remove differ only when the queue is empty: poll returns null, while remove throws NoSuchElementException. Choose the method that matches your error-handling style.

How LinkedList Implements Queue Operations

LinkedList is a doubly-linked list where each node holds a reference to the previous and next node. It maintains first and last pointers. Adding to the tail (offer) creates a new node and updates the last pointer. Removing from the head (poll) updates the first pointer and clears the node's references to help garbage collection. Both operations are O(1) because they only involve updating a few pointers.

This constant-time behavior is the main reason LinkedList can serve as a queue. However, the cost of each operation includes allocating a new node object for every insertion. This overhead is significant compared to array-based queues.

LinkedList vs ArrayDeque for Queue Use

ArrayDeque is the other common Queue implementation. It uses a resizable circular array and also provides O(1) add and remove at both ends. In most scenarios, ArrayDeque is preferable to LinkedList for queue usage because:

  • It does not allocate a node object per element, reducing memory footprint.
  • Elements are stored contiguously, which improves cache locality and often yields better throughput.
  • It does not allow null elements, which can be a benefit if you want to avoid null in your queue.

LinkedList allows null elements, which can be useful if you need to store null values. Also, if you need to remove elements from the middle of the queue or perform list operations, LinkedList gives you that flexibility. But for a pure FIFO queue, ArrayDeque is typically the better choice.

Thread Safety and Concurrent Queue Alternatives

LinkedList is not thread-safe. If multiple threads access a LinkedList as a queue, you must synchronize externally. The Collections.synchronizedQueue wrapper can provide thread safety, but it locks the entire queue for each operation, which may become a bottleneck.

For concurrent producer-consumer scenarios, consider ConcurrentLinkedQueue, which is lock-free and designed for high concurrency. Or use LinkedBlockingQueue if you need blocking behavior with capacity limits. These classes implement Queue but are not based on LinkedList internally.

When to Choose LinkedList as a Queue

Use LinkedList as a queue when:

  • You need to store null elements.
  • You need to remove elements from the middle of the queue (e.g., using remove(Object)).
  • You already have a LinkedList and want to avoid converting to another structure.
  • You need both list and queue behavior on the same object.

Otherwise, prefer ArrayDeque for better performance and lower memory overhead. The choice depends on whether the flexibility of a linked list outweighs the efficiency of an array-based deque.

java linkedlist as queue: Practical Usage and Code Examples | RYUSLOG DEV