Skip to content

Sequenced Collections Interview Questions & Answers

11 questions Updated 2026-06-20 Share:

Java sequenced collections interview questions — SequencedCollection, SequencedSet, SequencedMap, getFirst/getLast, addFirst/addLast, reversed(), which collections implement the new interfaces, and migration from workarounds.

Read the in-depth guideJava Sequenced Collections — getFirst, getLast, and reversed() for Every Ordered Type(opens in new tab)
11 of 11

Sequenced collections (Java 21, JEP 431) introduce three new interfaces — SequencedCollection, SequencedSet, and SequencedMap — that give a uniform API for accessing the first and last elements and for iterating in reverse order across all ordered collection types.

Before Java 21 each collection had its own non-uniform way to get the first or last element:

List<String> list = List.of("a", "b", "c");
list.get(0);                           // first element
list.get(list.size() - 1);             // last element — verbose

Deque<String> deque = new ArrayDeque<>(list);
deque.peekFirst();                     // first
deque.peekLast();                      // last

SortedSet<String> sorted = new TreeSet<>(list);
sorted.first();                        // first
sorted.last();                         // last

SequencedCollection unifies these with getFirst() / getLast().

Rule of thumb: if you need the first or last element, check whether the collection is a SequencedCollection and use the new API.

SequencedCollection<E> extends Collection<E> and adds:

Method Description
getFirst() Returns the first element; throws NoSuchElementException if empty
getLast() Returns the last element; throws NoSuchElementException if empty
addFirst(E) Inserts at the beginning (optional — throws UnsupportedOperationException for fixed-size)
addLast(E) Inserts at the end (optional)
removeFirst() Removes and returns the first element (optional)
removeLast() Removes and returns the last element (optional)
reversed() Returns a reversed view of the collection
List<String> list = new ArrayList<>(List.of("a", "b", "c"));

System.out.println(list.getFirst()); // "a"
System.out.println(list.getLast());  // "c"

list.addFirst("z");                  // ["z", "a", "b", "c"]
list.addLast("x");                   // ["z", "a", "b", "c", "x"]

list.removeFirst();                  // "z" removed
list.removeLast();                   // "x" removed

Rule of thumb: getFirst()/getLast() replace get(0) and get(list.size()-1) — use them for cleaner, more readable code.

SequencedSet<E> extends both SequencedCollection<E> and Set<E>, adding no new methods but guaranteeing both the set contract (no duplicates) and a defined encounter order.

Implementing classes:

  • LinkedHashSet — insertion-ordered set, implements SequencedSet
  • SortedSet subtypes: TreeSet — sorted, implements SequencedSet via SortedSet (which extends SequencedSet)
SequencedSet<String> set = new LinkedHashSet<>(List.of("b", "a", "c"));
System.out.println(set.getFirst()); // "b" — insertion order
System.out.println(set.getLast());  // "c"
System.out.println(set.reversed()); // ["c", "a", "b"] — reversed view

Rule of thumb: SequencedSet lets you treat LinkedHashSet and TreeSet uniformly when you need first/last/reversed without knowing the concrete type.

SequencedMap<K,V> extends Map<K,V> and adds methods to access the first and last entries:

Method Description
firstEntry() Returns (but does not remove) the first Map.Entry
lastEntry() Returns the last Map.Entry
pollFirstEntry() Removes and returns the first entry
pollLastEntry() Removes and returns the last entry
putFirst(K, V) Inserts/moves entry to the front (optional)
putLast(K, V) Inserts/moves entry to the back (optional)
reversed() Returns a reversed-order map view
sequencedKeySet() Returns a SequencedSet<K>
sequencedValues() Returns a SequencedCollection<V>
sequencedEntrySet() Returns a SequencedSet<Map.Entry<K,V>>
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.put("a", 1); map.put("b", 2); map.put("c", 3);

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

map.putFirst("z", 0);                // {z=0, a=1, b=2, c=3}

Rule of thumb: SequencedMap lets you use LinkedHashMap and TreeMap with a uniform first/last/reversed API without casting.

The new interfaces are retrofitted onto the existing type hierarchy:

Collection Implements
ArrayList, LinkedList, ArrayDeque SequencedCollection
LinkedHashSet SequencedSet
TreeSet SequencedSet (via SortedSet)
LinkedHashMap SequencedMap
TreeMap SequencedMap (via SortedMap)
List (interface) SequencedCollection
Deque (interface) SequencedCollection
SortedSet (interface) SequencedSet
SortedMap (interface) SequencedMap
SequencedCollection<Integer> col = new ArrayDeque<>(List.of(1, 2, 3));
col.getFirst(); // 1
col.getLast();  // 3

Rule of thumb: if the concrete type is ArrayList, LinkedHashSet, TreeMap, etc. you already have the new methods — no migration needed.

reversed() returns a live, write-through view of the collection in reverse encounter order. Mutations through the reversed view are reflected in the original, and vice versa.

List<String> list = new ArrayList<>(List.of("a", "b", "c"));
List<String> rev  = list.reversed();

System.out.println(rev);   // [c, b, a]

rev.addFirst("z");         // adds to the reversed view's front
System.out.println(list);  // [a, b, c, z]  — "z" is at the END of original

list.add("x");             // adds to original
System.out.println(rev);   // [x, z, c, b, a] — reflected in reversed view

Rule of thumb: reversed() is a live view, not a copy — mutations propagate both ways; if you need an independent copy, copy it explicitly.

For List implementations, getFirst() is equivalent to get(0) except for the exception when the list is empty. get(0) throws IndexOutOfBoundsException; getFirst() throws NoSuchElementException.

List<String> empty = new ArrayList<>();

empty.get(0);      // IndexOutOfBoundsException: Index 0 out of bounds
empty.getFirst();  // NoSuchElementException

List<String> list = List.of("a", "b", "c");
list.get(0);       // "a"
list.getFirst();   // "a" — same result

The semantic difference: IndexOutOfBoundsException signals a programming error (index miscalculation); NoSuchElementException signals an empty collection. getFirst() better expresses intent.

Rule of thumb: prefer getFirst() / getLast() over get(0) and get(size-1) — the intent is clearer and the exception type is more semantically correct.

Deque already had peekFirst()/peekLast(), pollFirst()/pollLast(), addFirst()/addLast(). The new SequencedCollection essentially makes these methods available on all ordered collections uniformly:

Deque method SequencedCollection equivalent
peekFirst() getFirst()
peekLast() getLast()
pollFirst() removeFirst()
pollLast() removeLast()
addFirst(e) addFirst(e)
addLast(e) addLast(e)

Deque itself now extends SequencedCollection, so ArrayDeque and LinkedList implement both and can be used interchangeably with either API.

Rule of thumb: Deque and SequencedCollection now share the first/ last API — prefer SequencedCollection in method signatures when you don't need Deque-specific operations like push()/pop().

Yes. List now extends SequencedCollection, so all List instances — including List.of() (immutable), Collections.unmodifiableList(), and Arrays.asList() — have getFirst()/getLast():

List<String> immutable = List.of("a", "b", "c");
System.out.println(immutable.getFirst()); // "a" — works fine
System.out.println(immutable.getLast());  // "c"

// Mutation methods throw UnsupportedOperationException on immutable lists:
immutable.addFirst("z"); // UnsupportedOperationException

Rule of thumb: getFirst()/getLast() are safe on any List, including immutable ones; mutation methods follow the same modifiability rules as before.

Each collection type needed a different API:

// List — verbose index arithmetic:
String first = list.get(0);
String last  = list.get(list.size() - 1);

// LinkedList (as Deque) — dedicated methods:
String first = ((LinkedList<String>) list).getFirst();

// ArrayDeque:
String first = deque.peekFirst();
String last  = deque.peekLast();

// SortedSet / TreeSet:
String first = sortedSet.first();
String last  = sortedSet.last();

// Iterating in reverse — no unified API:
Collections.reverse(list); // mutates the list!
// Or:
ListIterator<String> it = list.listIterator(list.size());
while (it.hasPrevious()) System.out.println(it.previous());

SequencedCollection replaces all of these with getFirst(), getLast(), and reversed().

Rule of thumb: if you wrote list.get(list.size()-1) before Java 21, replace it with list.getLast() — it is shorter and communicates intent.

Use SequencedCollection<E> (or SequencedMap<K,V>) in method signatures when your method specifically needs first/last access or reverse iteration but doesn't need to know the concrete type:

// Accept any ordered collection with first/last semantics:
static <T> T middle(SequencedCollection<T> col) {
    // Use getFirst/getLast without caring if it's ArrayList or LinkedHashSet
    if (col.isEmpty()) throw new NoSuchElementException();
    // ... navigate to middle via iterator
}

// Too narrow — only works for List:
static <T> T middle(List<T> list) { ... }

// Too broad — Collection doesn't guarantee order:
static <T> T middle(Collection<T> col) { ... } // getFirst() doesn't exist

Rule of thumb: prefer SequencedCollection over List in signatures when order and first/last access matter but random index access (get(i)) does not.

More ways to practice

The self-quiz is live. Get notified when mock interviews and new question packs drop.

or
Join our WhatsApp Channel