Back to Blog
Java

Java LinkedList getFirst: Usage and Pitfalls

java linkedlist getfirst: Learn how to use LinkedList.getFirst() in Java, handle empty lists, and understand its performance and alternatives.

JavaLinkedListDequegetFirstException Handling
Diagram showing a Java LinkedList with the getFirst() method pointing to the head node, with an empty list warning.

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

The getFirst() method on a Java LinkedList returns the first element of the list without removing it. It is part of the Deque interface, which LinkedList implements. The method throws NoSuchElementException if the list is empty. This article explains how to use getFirst() correctly, how it differs from peekFirst(), and what to watch for in performance-sensitive code.

What getFirst() Does and When to Use It

getFirst() is a direct accessor that retrieves the head of the list. Because LinkedList maintains a reference to its first node, the operation completes in constant time, O(1). This makes it a natural choice when you need to inspect the first element without altering the list structure.

import java.util.LinkedList; LinkedList<String> tasks = new LinkedList<>(); tasks.add("compile"); tasks.add("test"); tasks.add("deploy"); String firstTask = tasks.getFirst(); System.out.println(firstTask); // prints "compile"

The method is defined in the Deque interface, so any Deque implementation that supports it—such as ArrayDeque—also exposes getFirst(). However, LinkedList is the most common implementation when you need list-like behavior alongside deque operations.

The Difference Between getFirst() and peekFirst()

The most important distinction is how they handle an empty list. getFirst() throws NoSuchElementException, while peekFirst() returns null. This difference is critical in code that may encounter an empty collection.

LinkedList<String> empty = new LinkedList<>(); // Throws NoSuchElementException // String value = empty.getFirst(); // Returns null String value = empty.peekFirst();

Choose peekFirst() when the absence of an element is a normal condition and you want to avoid exception overhead. Use getFirst() when an empty list is a genuine error condition and you want the failure to surface immediately. The exception provides a clear signal that the program state is invalid, which can be preferable to silently handling null.

Handling an Empty LinkedList

If you call getFirst() on an empty list, the JVM throws NoSuchElementException. In many applications, this is an appropriate fail-fast behavior. You can catch it explicitly if you need to provide a fallback.

LinkedList<Integer> queue = new LinkedList<>(); try { int next = queue.getFirst(); process(next); } catch (NoSuchElementException e) { log("Queue is empty, waiting for new items"); }

Alternatively, you can check isEmpty() before calling getFirst(). This is often clearer than relying on exceptions for control flow, especially if the empty state is expected.

if (!queue.isEmpty()) { int next = queue.getFirst(); process(next); }

The choice between exception handling and an explicit check depends on how often the empty case occurs. If it is rare and truly exceptional, catching the exception is fine. If it is a common branch in your logic, the explicit check avoids exception overhead and reads more naturally.

Performance Characteristics of getFirst() on LinkedList

LinkedList is a doubly-linked list. Each node holds a reference to the previous and next node, and the list object stores references to the head and tail. Retrieving the first element is a simple field access, so the time complexity is O(1).

This is identical to calling get(0) on an ArrayList, which also runs in constant time. The difference appears when you access elements at arbitrary positions: LinkedList.get(index) is O(n) because it must traverse the list, while ArrayList.get(index) is O(1). For the specific case of the first element, both are equally fast.

Memory usage is a different tradeoff. LinkedList uses more memory per element because each node stores two pointers. If your primary need is frequent access to the first element, ArrayDeque is often a better choice than LinkedList. ArrayDeque also implements Deque and provides getFirst() in O(1) with lower memory overhead and better cache locality. Use LinkedList when you also need list operations like insertion at arbitrary positions or when you rely on List semantics.

Common Mistakes When Using getFirst()

A frequent mistake is assuming getFirst() removes the element. It does not. To retrieve and remove the first element, use removeFirst() or pollFirst(). The latter returns null on an empty list, while removeFirst() throws NoSuchElementException.

Another mistake is using getFirst() on a Queue reference without realizing that the Queue interface does not declare this method. If you declare a variable as Queue<String>, you can only call element() (which throws) or peek() (which returns null). To use getFirst(), declare the variable as Deque<String> or LinkedList<String>.

Queue<String> queue = new LinkedList<>(); // queue.getFirst(); // compile error Deque<String> deque = new LinkedList<>(); deque.getFirst(); // works

Finally, be careful when using getFirst() in a loop that also modifies the list. If you remove elements while iterating, the list may become empty unexpectedly. Always ensure the list is non-empty before calling getFirst(), or handle the exception in a way that does not break the loop logic.

Alternatives to getFirst() for Different Data Structures

If you are using an ArrayList, there is no getFirst() method. The equivalent is get(0). For an array, you would use index 0. For a Stack, you might use peek(). The choice of data structure should align with the operations you perform most often.

Data StructureMethod to get first elementBehavior on empty
LinkedListgetFirst()Throws NoSuchElementException
ArrayDequegetFirst()Throws NoSuchElementException
ArrayListget(0)Throws IndexOutOfBoundsException
Queueelement()Throws NoSuchElementException
Queuepeek()Returns null

When you need a non-throwing alternative, peekFirst() on Deque or peek() on Queue returns null. If null is a valid element in your collection, you may need to use contains() or isEmpty() to distinguish between an empty list and a null first element.

Using getFirst() with Deque and Queue Interfaces

Because LinkedList implements both List and Deque, the method you choose depends on the interface you are programming against. If you are working with a Deque reference, getFirst() is available. If you are working with a Queue reference, you must use element() or peek().

Deque<String> deque = new LinkedList<>(); deque.addFirst("first"); String head = deque.getFirst();

This interface distinction matters in library code where you accept a Queue parameter. The caller might pass a LinkedList, but you cannot call getFirst() on a Queue variable. You would need to cast, which is fragile, or use the Queue API. Prefer the interface that matches your actual requirements: use Deque when you need both ends, and Queue when FIFO semantics are sufficient.

In performance-critical code, the choice of implementation is more significant than the method call itself. ArrayDeque is generally faster and more memory-efficient than LinkedList for pure deque operations. Reserve LinkedList for cases where you need indexed access or frequent insertion in the middle. For the specific operation of retrieving the first element, all implementations are O(1), but the constant factors and memory footprint differ.

When you design a method that consumes a collection and only needs the first element, consider accepting a Deque and calling getFirst(). This communicates the requirement clearly and avoids the ambiguity of null returns. If the empty case is a normal part of your workflow, peekFirst() is the safer choice. The key is to match the method to the expected state of the collection and to be explicit about whether an empty list is an error or a valid condition.

java linkedlist getfirst: Practical Usage and Code Examples | RYUSLOG DEV