Introduction
The Java Collections Framework has been one of Java’s greatest strengths since Java 1.2.
Enterprise developers use collections everywhere:
- REST APIs
- Spring Boot applications
- Database queries
- Cache implementations
- Message processing
- Batch jobs
- Data transformation
- Stream processing
Despite its maturity, the Collections Framework had one long-standing inconsistency.
Some collections maintained insertion order.
Others maintained sorted order.
Others had no defined order.
More importantly, there was no common API to consistently access:
- The first element
- The last element
- A reversed view
Developers often wrote collection-specific code.
For example:
LinkedList<String> list = new LinkedList<>();
list.getFirst();
list.getLast();
But if the implementation changed to an ArrayList, these methods were no longer available.
Similarly, obtaining the first entry from a LinkedHashMap required iterating over the map.
Java 21 introduces Sequenced Collections, bringing consistency to ordered collections while remaining fully backward compatible.
Learning Objectives
By the end of this article, you will be able to:
- Understand why Sequenced Collections were introduced.
- Learn the new collection interfaces.
- Access first and last elements consistently.
- Reverse collections without copying.
- Work with ordered Maps and Sets.
- Apply these APIs in enterprise applications.
- Understand backward compatibility.
The Problem Before Java 21
Suppose we have:
List<String> users =
List.of(
"Rahul",
"John",
"Alice");
Accessing the first element:
users.get(0);
Accessing the last element:
users.get(users.size()-1);
Although this works, it only applies to indexed lists.
Now consider:
LinkedHashSet<String>
There was no equivalent API.
The same problem existed for ordered maps.
Java 21 Solution
Java introduces three new interfaces.
SequencedCollection
↓
SequencedSet
↓
SequencedMap
These interfaces define a consistent contract for ordered collections.
SequencedCollection
Provides operations such as:
collection.getFirst();
collection.getLast();
collection.reversed();
These methods work regardless of the underlying implementation, as long as it has a defined encounter order.
Getting the First Element
Instead of:
list.get(0);
Use:
collection.getFirst();
The intent is much clearer.
Getting the Last Element
Instead of:
list.get(list.size()-1);
Use:
collection.getLast();
No index calculations are required.
Reversed View
One of the most useful additions is:
collection.reversed();
Example:
List<String> names =
List.of(
"Rahul",
"John",
"Alice");
names.reversed()
.forEach(System.out::println);
Output:
Alice
John
Rahul
The reversed collection is a view, not a copied collection, so changes (where supported by the underlying collection) are reflected in both.
SequencedSet
Applicable to ordered sets such as:
LinkedHashSetTreeSet
Example:
SequencedSet<String> cities =
new LinkedHashSet<>();
cities.add("Delhi");
cities.add("Mumbai");
cities.add("Bengaluru");
System.out.println(cities.getFirst());
System.out.println(cities.getLast());
Previously, retrieving the first or last element often required iterator-based code.
SequencedMap
Maps now gain similar capabilities.
Example:
SequencedMap<Integer, String> employees =
new LinkedHashMap<>();
employees.put(1, "Rahul");
employees.put(2, "John");
employees.put(3, "Alice");
Retrieve:
employees.firstEntry();
employees.lastEntry();
Reverse iteration:
employees.reversed();
This is particularly useful for ordered caches, audit logs, and processing recent entries.
Enterprise Example – Audit Log
Suppose an application maintains an in-memory audit log using a LinkedHashMap.
Before Java 21, obtaining the most recent entry required iterating over the map or maintaining additional state.
With a SequencedMap:
Map.Entry<Long, AuditEvent> latest =
auditEvents.lastEntry();
The code is clearer and avoids unnecessary iteration.
Enterprise Example – Recent Notifications
A notification service stores the most recent notifications in insertion order.
SequencedCollection<Notification> notifications =
...
Displaying the newest notification becomes straightforward:
Notification latest =
notifications.getLast();
Enterprise Example – API Response History
Imagine maintaining the last ten API responses for diagnostics.
responses.reversed()
.forEach(System.out::println);
The newest responses appear first without creating a separate reversed copy.
Backward Compatibility
One of the strengths of this enhancement is that existing collection implementations were updated to implement the new interfaces where appropriate.
That means you can often adopt the new methods without changing your underlying data structures.
Performance Considerations
The new methods primarily improve expressiveness and consistency.
For most common ordered collections, operations such as retrieving the first or last element remain efficient because they leverage the underlying implementation.
The reversed() method returns a view rather than copying the collection, reducing unnecessary allocations.
Common Mistakes
Assuming Every Collection Is Sequenced
Not all collections have a defined encounter order.
For example:
HashSetHashMap
do not guarantee ordering and therefore are not appropriate where sequence is required.
Using Reversed Views as Independent Copies
reversed() provides a view.
If an independent snapshot is required, create a new collection explicitly.
Choosing Ordered Collections Without a Business Need
Maintaining order has a cost.
Use sequenced collections only when the application genuinely depends on encounter order.
Best Practices
✔ Use getFirst() and getLast() instead of index calculations where available.
✔ Use reversed() for reverse traversal instead of manual loops.
✔ Prefer LinkedHashMap or LinkedHashSet when insertion order matters.
✔ Select the collection implementation based on business requirements rather than convenience.
✔ Write against the new interfaces when order is an explicit part of the API contract.
Interview Questions
Why were Sequenced Collections introduced?
To provide a consistent API for ordered collections, allowing developers to access the first and last elements and traverse collections in reverse without relying on implementation-specific methods.
What are the new interfaces?
SequencedCollectionSequencedSetSequencedMap
Does reversed() create a new collection?
No.
It returns a reversed view of the original collection.
Can HashMap be treated as a SequencedMap?
No.
HashMap does not define a stable encounter order.
Why is this useful in enterprise applications?
It simplifies working with ordered data such as audit logs, recent events, caches, notification histories, and API response tracking while making code more readable and portable across collection implementations.
Summary
Sequenced Collections bring long-awaited consistency to the Java Collections Framework. By introducing common interfaces for ordered collections and providing intuitive methods such as getFirst(), getLast(), and reversed(), Java 21 reduces boilerplate and encourages developers to write against clear abstractions rather than concrete implementations.
While this feature may not be as revolutionary as Virtual Threads or Records, it is one of those quality-of-life improvements that enterprise developers will appreciate in everyday coding. Small enhancements like these collectively make modern Java more expressive, consistent, and enjoyable to use.
Coming Up Next
Part 40 – Java 21: Foreign Function & Memory API (Project Panama) – Calling Native Code Without JNI
We’ll explore:
- Why JNI has been difficult to use
- The goals of Project Panama
- Foreign Function & Memory API fundamentals
- Interacting with native libraries
- Memory segments
- Performance considerations
- Enterprise use cases
- When (and when not) to use this API
Even if you never write native integrations, understanding Project Panama helps you appreciate the future direction of the Java platform and why it aims to make native interoperability safer and simpler.