Back to Blog
Java

Java LinkedList as Queue: Implementation and Tradeoffs

Learn how to use Java's LinkedList as a queue, including FIFO behavior, offer/poll/peek methods, thread-safety considerations, and when ArrayDeque is usually the better choice.

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

Using Java's LinkedList as a queue is straightforward because LinkedList implements the Deque interface, which extends Queue. You can assign a LinkedList instance to a Queue reference and use the FIFO operations defined by the Queue interface.

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

offer 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. Because the variable is typed as Queue, callers can use only queue operations, which makes the FIFO intent explicit.

Queue Operations: offer, poll, and peek

The Queue interface provides two styles of methods: one that returns null or false on failure, and another that throws an exception. LinkedList implements both.

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

For LinkedList, the offer method returns true because the list has no fixed capacity, so add and offer behave the same way under normal conditions. poll and remove differ only when the queue is empty: poll returns null, while remove throws NoSuchElementException. Choose the method that fits your error-handling style.

How LinkedList Implements Queue Operations

LinkedList is a doubly-linked list. Each node holds references to the previous node, the next node, and its element. The list also keeps first and last pointers. Adding to the tail creates a new node and updates the last pointer; removing from the head updates the first pointer and unlinks the old head. Both operations run in O(1) time.

That constant-time behavior is why LinkedList can serve as a queue. However, every insertion allocates a new node object, and each element also stores two extra references. This overhead matters compared with an array-based queue.

LinkedList vs ArrayDeque for Queue Use

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

  • It does not allocate a node object per element, so memory usage is lower.
  • Elements are stored in a compact array, which improves cache locality and often improves throughput.
  • It does not allow null elements, which can help avoid null values in the queue.

LinkedList allows null elements, which can be useful if your data model requires them. It also supports list operations, so you can remove elements from the middle or use indexed access when needed. But if you need 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 the queue, you must synchronize externally. There is no Collections.synchronizedQueue helper, so you need explicit synchronization or a concurrent collection.

For concurrent producer-consumer scenarios, consider ConcurrentLinkedQueue, a lock-free queue designed for high concurrency. If you need blocking behavior with capacity limits, LinkedBlockingQueue is a common alternative. These classes implement the Queue interface 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 or perform other List operations; these methods are not in the Queue interface, so you would use a LinkedList-typed reference to call them.
  • 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 comes down to whether the flexibility of a linked list outweighs the efficiency of an array-based deque.

Using Java LinkedList as a Queue: FIFO Methods and Tradeoffs | RYUSLOG DEV