6.4 Sequenced Collections in Java 21

Key Takeaways

  • Java 21 introduces JEP 431 with three core interfaces: SequencedCollection<E>, SequencedSet<E>, and SequencedMap<K, V> to represent collections with a defined encounter order.
  • SequencedCollection provides uniform first and last element access: getFirst(), getLast(), addFirst(), addLast(), removeFirst(), removeLast(), and reversed().
  • The reversed() method produces an O(1) live, mutating reverse-ordered view where changes in the view immediately reflect in the backing collection and vice versa.
  • LinkedHashSet implements SequencedSet with special relocation semantics: addFirst(e) and addLast(e) relocate an existing element to the requested endpoint.
  • Standard hash collections (HashSet and HashMap) do NOT implement Sequenced interfaces because they lack a defined encounter order.
Last updated: September 2026

Sequenced Collections in Java 21 (JEP 431)

One of the most impactful features introduced in Java SE 21 and heavily tested on the 1Z0-830 exam is Sequenced Collections (JEP 431). Prior to Java 21, the Java Collections Framework lacked a unified hierarchy to represent collections with a defined encounter order, consistent first/last element access, and uniform reverse-order iteration.


1. The Historical Gap in the Collections Framework

Before Java 21, different collection types had disparate, inconsistent APIs for accessing endpoint elements and iterating in reverse:

Collection TypeAccess First ElementAccess Last ElementReverse Iteration
Listlist.get(0)list.get(list.size() - 1)ListIterator moving backward
Dequedeque.getFirst()deque.getLast()deque.descendingIterator()
SortedSetset.first()set.last()((NavigableSet) set).descendingSet()
LinkedHashSetset.iterator().next()Requires full iteration $O(n)$!No direct API (requires copying)

This fragmentation created friction: there was no common interface for "a collection that has a first element, a last element, and can be traversed in reverse."

JEP 431 retrofits the Java Collections Framework by introducing three new core interfaces:

  1. SequencedCollection<E>
  2. SequencedSet<E>
  3. SequencedMap<K, V>

2. The SequencedCollection<E> Interface Architecture

SequencedCollection<E> represents a collection whose elements have a well-defined encounter order (a first element, a second element, and so on up to the last element).

package java.util;

public interface SequencedCollection<E> extends Collection<E> {
    // Reverse-ordered view
    SequencedCollection<E> reversed();

    // Endpoint access methods
    void addFirst(E e);
    void addLast(E e);
    E getFirst();
    E getLast();
    E removeFirst();
    E removeLast();
}

Retrofitted Interface Hierarchy

SequencedCollection is integrated into the existing hierarchy as a parent of List, Deque, and SequencedSet:

                    Collection<E>
                          ▲
                          │
                SequencedCollection<E>
                 ▲        ▲         ▲
                 │        │         │
              List<E>  Deque<E>  SequencedSet<E>
                                  ▲         ▲
                                  │         │
                     LinkedHashSet<E>  SortedSet<E> / NavigableSet<E>

Method Semantics and Exception Behavior

  • getFirst() / getLast(): Returns the first or last element. If the collection is empty, throws NoSuchElementException.
  • removeFirst() / removeLast(): Removes and returns the first or last element. If the collection is empty, throws NoSuchElementException.
  • addFirst(e) / addLast(e): Inserts element at the designated endpoint. Throws UnsupportedOperationException if the collection is unmodifiable or if the collection is sorted (TreeSet).
List<String> list = new ArrayList<>(List.of("Alpha", "Beta", "Gamma"));

System.out.println(list.getFirst()); // "Alpha"
System.out.println(list.getLast());  // "Gamma"

list.addFirst("First");
list.addLast("Last");
System.out.println(list); // [First, Alpha, Beta, Gamma, Last]

String removed = list.removeFirst(); // "First"

[!CAUTION] Empty Collection Exception: Unlike Deque.peekFirst() / pollFirst() which return null on an empty deque, SequencedCollection.getFirst() and removeFirst() throw NoSuchElementException when called on an empty collection!


3. Bidirectional reversed() Views

The reversed() method returns a live, reverse-ordered view of the underlying sequenced collection. It does not copy or clone elements, operating in $O(1)$ time and memory.

Live View Mutability Dynamics

Because reversed() produces a dynamic view rather than a snapshot:

  • Mutations made to the reversed() view are immediately reflected in the original collection.
  • Mutations made to the original collection are immediately visible in the reversed view.
  • Calling addFirst() on the reversed view appends the element to the end of the original collection!
  • Calling removeFirst() on the reversed view removes the last element of the original collection!
  • Invoking .reversed().reversed() returns the original collection instance.
List<String> original = new ArrayList<>(List.of("A", "B", "C"));
SequencedCollection<String> reversedView = original.reversed();

System.out.println(reversedView); // [C, B, A]

// Adding to the head of reversed view -> Appends to the tail of original!
reversedView.addFirst("Z");
System.out.println("Original: " + original);      // [A, B, C, Z]
System.out.println("Reversed: " + reversedView);  // [Z, C, B, A]

// Removing from the head of reversed view -> Removes from tail of original!
reversedView.removeFirst(); // Removes "Z"
System.out.println("Original: " + original);      // [A, B, C]

4. SequencedSet<E> and LinkedHashSet Relocation Semantics

SequencedSet<E> extends both Set<E> and SequencedCollection<E>, combining set uniqueness with a defined encounter order:

package java.util;

public interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
    @Override
    SequencedSet<E> reversed();
}

Implementations include:

  • LinkedHashSet<E>: Maintains insertion/access encounter order.
  • TreeSet<E> (via SortedSet / NavigableSet): Maintains sorted order.

Relocation Semantics in LinkedHashSet (High-Yield Exam Topic!)

In standard Set.add(e) behavior, if an element already exists in the set, the operation is a no-op and returns false without modifying the encounter order.

However, in Java 21, LinkedHashSet provides special relocation semantics for addFirst() and addLast():

  • addFirst(e): If e is already present, it is relocated from its current position to the first position of the encounter order!
  • addLast(e): If e is already present, it is relocated to the last position of the encounter order!
SequencedSet<String> set = new LinkedHashSet<>(List.of("A", "B", "C", "D"));
System.out.println("Initial: " + set); // [A, B, C, D]

// Standard add() does NOT change position of existing element
boolean added = set.add("B"); // returns false
System.out.println("After add('B'): " + set); // [A, B, C, D]

// addFirst() RELOCATES existing element "C" to the front!
set.addFirst("C");
System.out.println("After addFirst('C'): " + set); // [C, A, B, D]

// addLast() RELOCATES existing element "A" to the end!
set.addLast("A");
System.out.println("After addLast('A'): " + set);  // [C, B, D, A]

5. The SequencedMap<K, V> Interface API

SequencedMap<K, V> represents a map whose key-value mappings have a defined encounter order.

package java.util;

public interface SequencedMap<K, V> extends Map<K, V> {
    // Reverse-ordered map view
    SequencedMap<K, V> reversed();

    // Boundary entry access
    Entry<K, V> firstEntry();
    Entry<K, V> lastEntry();
    Entry<K, V> pollFirstEntry();
    Entry<K, V> pollLastEntry();

    // Boundary insertions / relocations
    V putFirst(K key, V value);
    V putLast(K key, V value);

    // Sequenced collection views
    SequencedSet<K> sequencedKeySet();
    SequencedCollection<V> sequencedValues();
    SequencedSet<Entry<K, V>> sequencedEntrySet();
}

Implementations of SequencedMap

  • LinkedHashMap<K, V>: Implements SequencedMap. putFirst() and putLast() insert or relocate mappings to the requested endpoint.
  • TreeMap<K, V> (via NavigableMap<K, V>): Implements SequencedMap. However, calling putFirst() or putLast() throws UnsupportedOperationException because entry positions are determined strictly by key comparisons!
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.putLast("Two", 2);
map.putLast("Three", 3);
map.putFirst("One", 1); // Inserts at head

System.out.println(map); // {One=1, Two=2, Three=3}
System.out.println(map.firstEntry()); // One=1
System.out.println(map.lastEntry());  // Three=3

// Polling retrieves AND removes the boundary entry
Map.Entry<String, Integer> polled = map.pollFirstEntry(); // Removes One=1
System.out.println("Polled: " + polled); // One=1
System.out.println("Remaining: " + map);  // {Two=2, Three=3}

6. Why HashSet and HashMap Do NOT Implement Sequenced Interfaces

A fundamental rule for the exam:

  • HashSet does NOT implement SequencedCollection or SequencedSet.
  • HashMap does NOT implement SequencedMap.
  • Hashtable and ConcurrentHashMap do NOT implement SequencedMap.

Hash tables distribute keys and elements into hash buckets based on hashCode(). Their iteration order depends on hash distribution, table capacity, and collisions. Because standard hash tables have no defined encounter order, implementing sequenced interfaces on them would violate the interface contract.


7. Unsupported Operations and Immutability

Collection InstancegetFirst() / getLast()addFirst() / addLast()reversed()
ArrayList, LinkedListSupportedSupportedSupported (mutable view)
ArrayDequeSupportedSupportedSupported (mutable view)
LinkedHashSetSupportedSupported (relocates)Supported (mutable view)
TreeSet / TreeMapSupportedThrows UnsupportedOperationExceptionSupported (descendingSet view)
List.of(...)SupportedThrows UnsupportedOperationExceptionSupported (unmodifiable view)
HashSet / HashMapNot Available (Compile error)Not AvailableNot Available

Unmodifiable Sequenced Collection Factory Wrappers

Java 21 added static wrapper methods in java.util.Collections:

SequencedCollection<T> unmodColl = Collections.unmodifiableSequencedCollection(seqColl);
SequencedSet<T> unmodSet = Collections.unmodifiableSequencedSet(seqSet);
SequencedMap<K, V> unmodMap = Collections.unmodifiableSequencedMap(seqMap);
Loading diagram...
Sequenced Collections Hierarchy and Bidirectional Reversed View Dynamics
Test Your Knowledge

What is the expected outcome of running the following Java 21 code snippet? List<String> emptyList = new ArrayList<>(); String first = emptyList.getFirst();

A
B
C
D
Test Your Knowledge

Consider the following Java 21 program: List<String> list = new ArrayList<>(List.of("A", "B", "C")); var rev = list.reversed(); rev.addFirst("Z"); System.out.println(list); What is printed to standard output?

A
B
C
D
Test Your Knowledge

Examine the following code using a LinkedHashSet in Java 21: SequencedSet<String> set = new LinkedHashSet<>(List.of("A", "B", "C")); set.addFirst("B"); System.out.println(set); What is the resulting encounter order printed by this code?

A
B
C
D
Test Your Knowledge

Which of the following statements regarding the SequencedMap interface in Java 21 is FALSE?

A
B
C
D