Java

Java 21 Sequenced Collections

Master the newest evolution in Java Collections. Learn SequencedCollection, SequencedSet, and SequencedMap interfaces that finally bring consistent first/last operations to the Collections Framework, plus how Virtual Threads change concurrent collection patterns.

📋 At a Glance

AspectDetails
TopicSequencedCollection, SequencedSet, SequencedMap, reversed(), Virtual Threads
ComplexityIntermediate
PrerequisitesPart 1 (Collection Framework Architecture), Part 21 (Blocking Queues)
Time to Master2-3 hours
Interview FrequencyRising (Modern Java knowledge)

🎯 What You'll Learn

After completing this article, you will be able to:

  1. Use SequencedCollection methods for first/last access
  2. Understand the new collection hierarchy with Sequenced interfaces
  3. Navigate collections in reverse with reversed() views
  4. Apply Virtual Threads patterns with blocking collections
  5. Migrate legacy code to use modern Sequenced APIs

Production Story: The First Element Frustration

The Incident

Our team maintained a data processing pipeline that needed to access first and last elements from various collection types. The code was a mess of workarounds:

JAVA(30 lines)
Code
Loading syntax highlighter...

The Problem

TEXT(17 lines)
Code
Loading syntax highlighter...

The Java 21 Solution

JAVA(21 lines)
Code
Loading syntax highlighter...

The Difference

TEXT(12 lines)
Code
Loading syntax highlighter...

Mental Model: The Double-Ended Collection

TEXT(47 lines)
Code
Loading syntax highlighter...

Deep Dive: The New Interface Hierarchy

SequencedCollection Interface

JAVA(46 lines)
Code
Loading syntax highlighter...

SequencedSet Interface

JAVA(12 lines)
Code
Loading syntax highlighter...

SequencedMap Interface

JAVA(64 lines)
Code
Loading syntax highlighter...

Complete Hierarchy

TEXT(42 lines)
Code
Loading syntax highlighter...

Deep Dive: Using Sequenced Methods

Basic Operations

JAVA(17 lines)
Code
Loading syntax highlighter...

reversed() Views

JAVA(18 lines)
Code
Loading syntax highlighter...

SequencedMap Operations

JAVA(29 lines)
Code
Loading syntax highlighter...

Iteration Patterns

JAVA(21 lines)
Code
Loading syntax highlighter...

Deep Dive: Virtual Threads and Collections

Virtual Threads Overview

JAVA(18 lines)
Code
Loading syntax highlighter...

Virtual Threads + Blocking Collections

JAVA(51 lines)
Code
Loading syntax highlighter...

Pattern: One-Virtual-Thread-Per-Request

JAVA(22 lines)
Code
Loading syntax highlighter...

Structured Concurrency with Collections (Preview)

JAVA(41 lines)
Code
Loading syntax highlighter...

Deep Dive: Migration to Sequenced Collections

Before and After Comparisons

JAVA(60 lines)
Code
Loading syntax highlighter...

Migration Patterns

JAVA(35 lines)
Code
Loading syntax highlighter...

⚠️ Common Mistakes

Mistake 1: Assuming reversed() Creates a Copy

JAVA(11 lines)
Code
Loading syntax highlighter...

Mistake 2: Using getFirst()/getLast() on Empty Collections

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 3: Expecting All Collections to Support addFirst/addLast

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 4: Confusing pollFirst with removeFirst

JAVA(16 lines)
Code
Loading syntax highlighter...

Mistake 5: Ignoring Thread Safety with Virtual Threads

JAVA(17 lines)
Code
Loading syntax highlighter...

🐛 Debug This

Challenge 1: The Disappearing Elements

JAVA(8 lines)
Code
Loading syntax highlighter...
✅ Answer:
ConcurrentModificationException! Even though you're removing from set, you're iterating over reversed which is a view of the same set.
Fix:
JAVA(15 lines)
Code
Loading syntax highlighter...

Challenge 2: The Stubborn TreeSet

JAVA(2 lines)
Code
Loading syntax highlighter...
✅ Answer:
UnsupportedOperationException! TreeSet doesn't support positional insertion because element position is determined by comparison, not insertion order.
Fix:
JAVA(6 lines)
Code
Loading syntax highlighter...

Challenge 3: The Virtual Thread Deadlock

JAVA(15 lines)
Code
Loading syntax highlighter...
✅ Answer:

Deadlock! Both threads are blocked:

  • Thread 1: waiting on queue2.take()
  • Thread 2: waiting on queue1.take()

Neither can proceed because neither has taken from the queue the other is waiting to take from.

Fix:
JAVA(11 lines)
Code
Loading syntax highlighter...

💻 Exercises

Exercise 1: Sequenced Collection Utilities

Create utility methods that work with any SequencedCollection:

JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(48 lines)
Code
Loading syntax highlighter...

Exercise 2: LRU Cache with SequencedMap

Implement an LRU cache using SequencedMap:

JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(41 lines)
Code
Loading syntax highlighter...

Exercise 3: Parallel Batch Processor with Virtual Threads

Create a batch processor that uses Virtual Threads:

JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(58 lines)
Code
Loading syntax highlighter...

🎤 Senior-Level Interview Questions

Question 1: Sequenced Collection Motivation

Q: Why were SequencedCollection interfaces added in Java 21? What problem do they solve?
A:

Before Java 21, ordered collections had inconsistent APIs:

JAVA(11 lines)
Code
Loading syntax highlighter...

SequencedCollection provides:

  1. Unified API: Same methods across all ordered collections
  2. Direct last access: LinkedHashSet finally has getLast()
  3. Reverse views: reversed() works everywhere
  4. Type safety: Compiler knows a collection has order

Question 2: reversed() View Semantics

Q: Is reversed() a copy or a view? What are the implications?
A:
It's a view, not a copy:
JAVA(10 lines)
Code
Loading syntax highlighter...

Implications:

  • Memory efficient (no copy)
  • Changes propagate both directions
  • Iteration can throw ConcurrentModificationException if original modified
  • Need explicit copy if independence required: new ArrayList<>(c.reversed())

Question 3: Virtual Threads Impact

Q: How do Virtual Threads change the patterns for using blocking collections?
A:

With platform threads, blocking was expensive:

  • Each blocked thread = OS thread blocked
  • Limited to ~10K platform threads
  • Had to use non-blocking patterns, async, reactive

With Virtual Threads, blocking is cheap:

  • Blocked virtual thread = carrier thread released
  • Millions of virtual threads possible
  • Simple blocking code scales
JAVA(12 lines)
Code
Loading syntax highlighter...

Question 4: Migration Strategy

Q: How would you migrate a codebase to use Sequenced Collections?
A:

Gradual migration strategy:

  1. Update method parameters (broadest impact):
JAVA(5 lines)
Code
Loading syntax highlighter...
  1. Replace workarounds:
JAVA(4 lines)
Code
Loading syntax highlighter...
  1. Simplify reverse iteration:
JAVA(6 lines)
Code
Loading syntax highlighter...
  1. Clean up instanceof checks:
JAVA(2 lines)
Code
Loading syntax highlighter...

Question 5: TreeSet and addFirst

Q: Why does TreeSet throw UnsupportedOperationException on addFirst()?
A:
TreeSet is ordered by comparison, not insertion order:
JAVA(16 lines)
Code
Loading syntax highlighter...

📝 Summary & Key Takeaways

New Interfaces

InterfaceKey MethodsImplementations
SequencedCollection<E>getFirst/Last, addFirst/Last, removeFirst/Last, reversed()ArrayList, LinkedList, ArrayDeque, LinkedHashSet, TreeSet
SequencedSet<E>(extends Set + SequencedCollection)LinkedHashSet, TreeSet, ConcurrentSkipListSet
SequencedMap<K,V>firstEntry, lastEntry, putFirst/Last, pollFirst/LastLinkedHashMap, TreeMap, ConcurrentSkipListMap

Key Points

  1. reversed() is a view - modifications affect both directions
  2. Not all methods supported everywhere - TreeSet doesn't support addFirst/Last
  3. Virtual Threads enable simple blocking patterns - embrace queue.take()
  4. Migration is gradual - update parameters to accept SequencedCollection

Virtual Threads Summary

  • Blocking collections now practical at scale
  • Simple code replaces complex async patterns
  • Structured Concurrency for coordinated tasks
  • Still need thread-safe collections for shared state

🏁 Conclusion

Java 21's Sequenced Collections and Virtual Threads represent a major evolution in Java development. Sequenced Collections finally unify the inconsistent APIs for ordered collections, while Virtual Threads make simple blocking code scalable again.

Key takeaways:

  1. Use SequencedCollection in method signatures for flexibility
  2. Understand reversed() is a view not a copy
  3. Virtual Threads make blocking cheap - write simple code
  4. Structured Concurrency for coordinated parallel work
  5. Gradual migration is safe - new interfaces extend existing ones

In the next article, we'll explore Streams and Collectors - powerful tools for transforming and aggregating collections that work beautifully with both traditional and sequenced collections.


📅 Review Schedule

To solidify your understanding, review this material:

  • Tomorrow: Practice getFirst()/getLast() with different collection types
  • In 3 days: Implement something using reversed() views
  • In 1 week: Try Virtual Threads with BlockingQueue
  • In 2 weeks: Review migration patterns for existing code