Comprehensive Guide to Sequenced Collections in Java

Target Java versions:
- Preview / Incubation: Early work in Java 20
- Final / Standard: Java 21 – JEP 431: Sequenced Collections

Sequenced Collections introduce new interfaces in java.util to give a uniform, explicit way to work with ordered collections:

  • SequencedCollection<E>
  • SequencedSet<E>
  • SequencedMap<K, V>

Before this, Java APIs were inconsistent about “first/last” elements and iteration order.


1. Motivation: Why Sequenced Collections?

Before Java 21:

  • List has index-based operations: get(0), get(size-1).
  • Deque has addFirst, addLast, getFirst, getLast, etc.
  • SortedSet / NavigableSet have first, last.
  • Map has no standard “first/last entry” concept (except SortedMap / NavigableMap with firstEntry / lastEntry).
  • Set generally has no ordering contract (except LinkedHashSet with insertion order, but API doesn’t expose first/last explicitly).

The result: no common interface to talk about “the first and last element” of an ordered collection, even though many collections are naturally ordered.

Sequenced Collections fix this by:

  • Providing an explicit concept of encounter order (the order you see elements when iterating).
  • Adding a uniform API for:
  • First element
  • Last element
  • Adding/removing at both ends
  • Reversed view

2. The New Interfaces

2.1. SequencedCollection<E>

  • Extends Collection<E>.
  • Adds operations for handling the first and last elements.
  • Introduces a reversed view.

Key methods (conceptually):

public interface SequencedCollection<E> extends Collection<E> {
    E getFirst();
    E getLast();
    E removeFirst();
    E removeLast();
    void addFirst(E e);
    void addLast(E e);
    SequencedCollection<E> reversed();
}

(Exact signatures may include default implementations where appropriate.)

This unifies many patterns that were previously scattered across List, Deque, etc.


2.2. SequencedSet<E>

  • Extends both Set<E> and SequencedCollection<E>.

Conceptually:

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

Intended for sets with a well-defined encounter order, e.g.:

  • LinkedHashSet – insertion order
  • SortedSet / NavigableSet – sorted order

2.3. SequencedMap<K, V>

  • Extends Map<K, V>.
  • Adds methods for first/last entries, reversed view, and insertion at front/back.

Conceptually:

public interface SequencedMap<K, V> extends Map<K, V> {
    Map.Entry<K, V> firstEntry();
    Map.Entry<K, V> lastEntry();
    Map.Entry<K, V> pollFirstEntry();
    Map.Entry<K, V> pollLastEntry();

    V putFirst(K key, V value);
    V putLast(K key, V value);

    SequencedMap<K, V> reversed();
}

This gives a consistent API for maps that maintain order, e.g.:

  • LinkedHashMap
  • SortedMap / NavigableMap implementations, etc.

3. Encounter Order

Encounter order = the order in which elements are encountered when iterating over the collection.

Key points:

  • List → encounter order = index order (0…size-1).
  • LinkedHashSet → insertion order (or access order if configured).
  • SortedSet / SortedMap → sorted according to comparator / natural order.
  • HashSet / HashMapno guaranteed encounter order → they do not implement Sequenced*.

Sequenced collections rely on this concept to define:

  • getFirst() → first element in encounter order.
  • getLast() → last element in encounter order.
  • reversed() → view whose encounter order is the reverse of the original.

4. Implementations in the Standard Library

With Java 21, many JDK classes now implement the new interfaces:

  • List<E>SequencedCollection<E>
  • Deque<E>SequencedCollection<E> (most likely)
  • LinkedHashSet<E>SequencedSet<E>
  • SortedSet<E> / NavigableSet<E> implementations → SequencedSet<E>
  • LinkedHashMap<K, V>SequencedMap<K, V>
  • SortedMap<K, V> / NavigableMap<K, V> implementations → SequencedMap<K, V>

Non-sequenced:

  • HashSet, HashMap – still not sequenced; they do not guarantee encounter order.

5. Key Methods and Semantics

5.1. getFirst() and getLast()

E first = coll.getFirst();
E last  = coll.getLast();
  • coll is a SequencedCollection<E>.
  • Throws an exception (typically NoSuchElementException) if empty.

Example:

SequencedCollection<String> sc = (SequencedCollection<String>) new ArrayList<>(List.of("A", "B", "C"));
System.out.println(sc.getFirst()); // "A"
System.out.println(sc.getLast());  // "C"

For List, this typically maps to:

  • getFirst()get(0)
  • getLast()get(size()-1)

5.2. addFirst(E e) and addLast(E e)

coll.addFirst("X");  // insert at the beginning
coll.addLast("Y");   // append at the end
  • For List, addFirst would be like add(0, e).
  • For Deque, they map naturally to addFirst / addLast.

Example:

SequencedCollection<Integer> sc = (SequencedCollection<Integer>) new LinkedList<>(List.of(1, 2, 3));
sc.addFirst(0);  // [0, 1, 2, 3]
sc.addLast(4);   // [0, 1, 2, 3, 4]

5.3. removeFirst() and removeLast()

E removedFirst = coll.removeFirst();
E removedLast  = coll.removeLast();
  • Remove and return the first / last element.
  • Throw NoSuchElementException if empty.

For Deque, these correspond to removeFirst / removeLast.
For List, they’re like remove(0) / remove(size-1).


5.4. reversed() — Reversed View

reversed() is a view, not a copy.

SequencedCollection<String> sc = (SequencedCollection<String>) new ArrayList<>(List.of("A", "B", "C"));

SequencedCollection<String> rev = sc.reversed();
System.out.println(rev); // logically ["C", "B", "A"]

Important:

  • Operations on the reversed view affect the original collection, and vice versa.
  • This is similar to how Collections.unmodifiableList returns a view.

Example behavior:

SequencedCollection<String> sc = (SequencedCollection<String>) new LinkedList<>(List.of("A", "B", "C"));
SequencedCollection<String> rev = sc.reversed();

rev.addFirst("Z");  // adds to *end* of original sc → sc = [A, B, C, Z]
rev.addLast("X");   // adds to *beginning* of original sc → sc = [X, A, B, C, Z]

So:

  • In rev order: [Z, C, B, A, X]
  • In sc order: [X, A, B, C, Z]

Reversed is conceptually “flipped view” of the same underlying data.


6. Sequenced Maps: Examples

6.1. Basic Use

SequencedMap<String, Integer> map =
    (SequencedMap<String, Integer>) new LinkedHashMap<String, Integer>();

map.putLast("b", 2);
map.putFirst("a", 1);
map.putLast("c", 3);

System.out.println(map.firstEntry()); // a=1
System.out.println(map.lastEntry());  // c=3

6.2. firstEntry, lastEntry, pollFirstEntry, pollLastEntry

Map.Entry<String, Integer> first = map.firstEntry();
Map.Entry<String, Integer> last  = map.lastEntry();

Map.Entry<String, Integer> removedFirst = map.pollFirstEntry(); // remove+return
Map.Entry<String, Integer> removedLast  = map.pollLastEntry();  // remove+return

Typical behavior:

  • firstEntry() / lastEntry() – view of first/last mapping; no structural modification.
  • pollFirstEntry() / pollLastEntry() – remove first/last mapping and return it; returns null if empty.

6.3. putFirst and putLast

map.putLast("x", 10);  // put (or move) mapping to end
map.putFirst("y", 20); // put (or move) mapping to start

Behaviors:

  • If key already exists:
  • Value is updated.
  • Entry moved to front/back accordingly.
  • If key is new:
  • Entry inserted at front/back.

This is particularly useful for LRU-like structures and custom caches.


6.4. reversed() on SequencedMap

SequencedMap<String, Integer> rev = map.reversed();
  • Gives a view of the same mappings in reversed encounter order.
  • Put/remove on the reversed view affects the underlying map.

Example:

map.putLast("a", 1);
map.putLast("b", 2);
map.putLast("c", 3);

SequencedMap<String, Integer> rev = map.reversed();
rev.putFirst("z", 0);  // add "z" as *last* in original map
rev.putLast("x", 9);   // add "x" as *first* in original map

7. Sequenced Sets: Examples

7.1. LinkedHashSet as SequencedSet

SequencedSet<String> set =
    (SequencedSet<String>) new LinkedHashSet<>(List.of("A", "B", "C"));

System.out.println(set.getFirst()); // "A"
System.out.println(set.getLast());  // "C"

set.addFirst("Z");  // now order: Z, A, B, C (no duplicates)
set.addLast("Y");   // Z, A, B, C, Y

addFirst / addLast preserve uniqueness semantics:

  • If element already exists, you must check how the concrete implementation handles it:
  • Typically: move to front or back (similar to LinkedHashMap semantics),
  • Or ignore re-insertion.

7.2. SortedSet / NavigableSet

For sorted sets, “first/last” is sorted order, not insertion order:

SequencedSet<Integer> s = (SequencedSet<Integer>) new TreeSet<>(Set.of(3, 1, 2));

System.out.println(s.getFirst()); // 1
System.out.println(s.getLast());  // 3

reversed() view will traverse in descending order.


8. Interactions With Streams and Iteration

Sequenced collections integrate smoothly with existing iteration patterns:

  • for-each loops respect encounter order.
  • stream() preserves encounter order (as before).
  • reversed() reversed view preserves its own encounter order when streamed.

Example:

SequencedCollection<String> sc =
    (SequencedCollection<String>) new ArrayList<>(List.of("A", "B", "C"));

sc.stream().forEach(System.out::println);
// A B C

sc.reversed().stream().forEach(System.out::println);
// C B A

9. Design Intent and Benefits

9.1. Unified API Across Ordered Collections

Previously, operations like “add at front” or “get last” were scattered:

  • Deque had its own methods.
  • List needed index-based work.
  • Sorted sets/maps had first/last but different naming patterns.

Now:

  • addFirst, addLast, getFirst, getLast, removeFirst, removeLast, reversed are standardized for all sequenced types.

9.2. Cleaner, More Expressive Code

Examples:

Before:

List<String> list = new ArrayList<>();
list.add(0, "first");
list.add("last");

String first = list.get(0);
String last  = list.get(list.size() - 1);

After:

SequencedCollection<String> sc = (SequencedCollection<String>) list;
sc.addFirst("first");
sc.addLast("last");

String first = sc.getFirst();
String last  = sc.getLast();

9.3. Fewer Special-Case APIs

Instead of introducing new class-specific methods, the JDK uses the new interfaces.


10. Limitations and Things to Watch Out For

10.1. Not All Collections are Sequenced

  • HashSet, HashMap, and some others do not implement sequenced interfaces.
  • They do not guarantee an encounter order.

If you need sequenced behavior, use:

  • LinkedHashSet
  • LinkedHashMap
  • List, Deque
  • Sorted / Navigable collections, etc.

10.2. Reversed Views Are Live

reversed() returns live views.

Things to remember:

  • Modifications through one view are reflected in the other.
  • Removing/adding via reversed() may be confusing if you don’t mentally track the semantics.

If you want an independent reversed copy:

SequencedCollection<String> rc = sc.reversed();
List<String> copy = new ArrayList<>(rc);  // copy

10.3. Exceptions on Empty Collections

getFirst, getLast, removeFirst, removeLast:

  • Typically throw NoSuchElementException when the collection is empty.
  • Use isEmpty() to guard, or better, use poll*-style APIs where available (on maps).

10.4. Performance Considerations

  • For ArrayList:
  • addLast is generally O(1) amortized.
  • addFirst may be O(n) due to element shifting.
  • For LinkedList / Deque:
  • addFirst/addLast are generally O(1).

Sequenced interfaces define semantics, not performance characteristics; you must still pick an appropriate implementation.


11. Best Practices & Patterns

✔ Prefer Sequenced Interfaces in APIs

void process(SequencedCollection<String> coll) { ... }

instead of:

void process(List<String> list) { ... }

if you only rely on “sequence” semantics rather than list-specific ones.

Similarly:

void process(SequencedMap<K, V> map) { ... }

to allow callers to pass LinkedHashMap, TreeMap, etc.


✔ Use Reversed Views Instead of Manual Reversal When You Want a View

SequencedCollection<E> rev = coll.reversed();

instead of:

List<E> copy = new ArrayList<>(coll);
Collections.reverse(copy);

The view is lazy and updates with the original.


✔ Model Queues/Deques With SequencedCollection

Many queue or deque-like operations can now use SequencedCollection instead of a specific Deque or List.


❌ Don’t Assume Hash-Based Collections Are Sequenced

If your code depends on encounter order:

  • Don’t use HashMap / HashSet directly.
  • Use LinkedHashMap / LinkedHashSet or other ordered variants.

12. Typical Interview Questions (With Answers)

Q1. What are Sequenced Collections?

A: A set of new interfaces (SequencedCollection, SequencedSet, SequencedMap) introduced in Java 21 that unify operations on collections with a well-defined encounter order (first/last, add/remove at ends, reversed view).


Q2. Which Java version introduced Sequenced Collections?

A: Java 21, via JEP 431.


Q3. Name key methods provided by SequencedCollection.

A: - addFirst, addLast
- getFirst, getLast
- removeFirst, removeLast
- reversed


Q4. Do HashSet or HashMap implement Sequenced interfaces?

A: No. They do not guarantee a stable encounter order and therefore are not sequenced.


Q5. What does reversed() return?

A: A live view of the same collection or map, but with the encounter order reversed.
Changes through either view are reflected in the other.


Q6. How do Sequenced Collections help with API design?

A: They provide a generic, uniform way to express “ordered collection” requirements in method signatures without tying the API to specific implementations (List, Deque, LinkedHashMap, etc.).


13. Summary

Sequenced Collections are a key enhancement in modern Java:

  • Introduced in Java 21 to unify and clarify the notion of ordered collections.
  • Provide consistent first/last/add/remove/reversed operations for:
  • Collections → SequencedCollection
  • Sets → SequencedSet
  • Maps → SequencedMap
  • Make APIs more expressive and easier to reason about.
  • Work seamlessly with existing implementations like List, Deque, LinkedHashSet, LinkedHashMap, and sorted collections.

They are especially important for interview preparation when discussing:

  • New Java language & library features
  • Collections framework evolution
  • API design and encounter order semantics

This guide should give you enough detail to use Sequenced Collections confidently in both interviews and real projects.