As a library author, when should you expose SequencedCollection in an API, and what are the trade-offs?
answer
- Weakest type that expresses the guarantee
- Accept = permissive; return = promises order, hides index
- Java 21+ floor
- No mutability guarantee — UOE possible; document it
- Views alias internal state → defensive copy
basics
~20 sUse SequencedCollection in a signature when callers genuinely need a defined order plus end access, but you don't want to lock them into List. Accept it as a parameter to be permissive; return it (or a narrower type) when order is part of your contract. Don't use it if order is irrelevant.
solid answer
~50 sExpose `SequencedCollection` (or `SequencedSet`/`SequencedMap`) when **order is a real part of the contract** and the caller needs end access or reversal, but you want to stay broader than a concrete `List`/`Deque`. As an input type it is permissive — you accept `ArrayList`, `LinkedList`, `ArrayDeque`, `LinkedHashSet`, `TreeSet`, etc. As a return type it *promises* a defined encounter order without committing to indexability, which is exactly right when you don't want callers depending on `get(index)`. Trade-offs: (1) it's Java 21+, so it raises your baseline; (2) it does **not** guarantee mutability — some implementations throw `UnsupportedOperationException` on `addFirst`/`addLast` (sorted types, immutable lists), so document whether your returned view is modifiable; (3) if callers only iterate, plain `Iterable`/`Collection` may suffice; if they need indexing, return `List`. Choose the **weakest type that still expresses the guarantee** you actually provide.
go deeper
Recognizes SequencedCollection as a possible parameter/return type but typically uses concrete types.
Picks SequencedCollection when order matters but List is too specific, and knows it needs Java 21.
Weighs accept-vs-return semantics, the no-mutability-guarantee caveat, and view-aliasing/encapsulation concerns.
Designs the abstraction ladder deliberately, manages the JDK version floor and contract evolution, and documents mutability/empty/aliasing guarantees across versions.
## The interface-design question A good Java API parameter/return type is the **weakest type that still expresses what the code needs or guarantees** ("require no more than you use; promise no more than you must"). `SequencedCollection` adds a new, useful rung on the abstraction ladder between `Collection` (no order guarantee) and `List` (order + index + duplicates) — namely: *defined encounter order with end access and reversal, but not necessarily indexable*. ## When to accept it as a parameter Use `SequencedCollection<E>` (or `SequencedSet`/`SequencedMap`) as an **input** when your method legitimately needs the order or end access (e.g. "process newest-first", "peek the head", "iterate reversed") but shouldn't force the caller to pass a `List`. This is more permissive than `List` — a caller with a `LinkedHashSet` or `ArrayDeque` can pass it directly. If your method merely iterates and order is irrelevant, accept `Collection` or `Iterable` instead; don't over-constrain. ## When to return it Return `SequencedCollection` when **order is part of your contract** but you deliberately want to **withhold indexability** so callers don't couple to `get(i)` (which would let them write O(n) loops on a linked structure, or bind them to a List you might swap out). Returning the Sequenced type documents "there is a meaningful first/last and a stable order" without overpromising random access. If callers truly need indexing, return `List`; if they need uniqueness + order, return `SequencedSet`. ## Trade-offs and pitfalls 1. **Version floor.** The interfaces exist only in **Java 21+**. Exposing them raises your library's minimum JDK and can't appear in code targeting older releases. 2. **No mutability guarantee.** A `SequencedCollection` reference may be backed by an immutable list (`List.of`) or a sorted set, where `addFirst`/`addLast` throw `UnsupportedOperationException`. The *type* says nothing about mutability — so **document** whether a returned sequenced view is modifiable, and whether mutations write through (if it's a view such as `reversed()`). 3. **View aliasing.** If you return `reversed()` or a sequenced view, the caller holds a live alias into your internal state. For encapsulation, return a defensive copy (`new ArrayList<>(internal)`) or an unmodifiable wrapper unless live coupling is intended. 4. **Empty-handling asymmetry.** `getFirst`/`getLast` throw on empty, while `SequencedMap.firstEntry` returns null — be deliberate and document which your API relies on. 5. **Don't reach for it reflexively.** If order isn't actually part of the meaning, `Collection`/`Set`/`Map` remain the honest choice; introducing `Sequenced*` implies a guarantee you must then uphold across versions. ## Migration angle Because `List`/`Deque`/`LinkedHashSet`/`Sorted*` were retrofitted, **existing return types automatically gained the new capabilities** — so you often don't need to change signatures at all; callers on Java 21 can already call `getFirst()`/`reversed()` on a returned `List`. Switch the *declared* type to `SequencedCollection` only when you want to *loosen* (accept more) or *tighten the order promise while loosening indexability* (return less).
- Why might you return SequencedCollection instead of List even though you internally use an ArrayList?To promise a defined order and end access while not committing callers to index-based access (get(i)), keeping you free to switch the backing structure and preventing accidental O(n) index loops on it.
- Your method returns sortedSet.reversed(). What should you warn callers about?It's a live view backed by your internal sorted set, and addFirst/addLast on it throw UnsupportedOperationException (sorted position is fixed). If you don't want aliasing, return a copy instead.
saying these in an interview costs you the question
- Returning a live reversed()/sequenced view of internal state without considering encapsulation
- Assuming a SequencedCollection parameter is always mutable
- Switching every List signature to SequencedCollection 'because it's newer' even when callers need indexing
- Ignoring that exposing it raises the minimum JDK to 21