A collection contract describes the operations a caller needs; its implementation determines ordering and performance.
List, set or map?
Select by behavior
- List: an ordered sequence that can contain duplicates.
- Set: membership with no duplicate elements under the implementation’s equality rules.
- Map: values associated with keys.
- Deque: insertions and removals at both ends.
Use ArrayList as a starting point for indexed sequence access. Consider ArrayDeque for endpoint work without null elements. Study LinkedList when cursor edits and the combined List/Deque contract matter.
A contract is narrower than an implementation
Declare List when callers need list operations, but choose the implementation from the actual workload. A contract-compatible substitution can still change performance: repeated indexed access that is cheap on an array-backed list is expensive on linked storage.
Map is not a Collection subtype. Its key set, value collection, and entry set expose views of the mappings with their own mutation rules. Decide whether the caller receives a live view or a copied snapshot.
Common Mistakes
Do not assume a Set preserves insertion order or a Map sorts keys. Those properties depend on the chosen implementation.
Choose an operation and a lifetime
Write the access pattern before naming a collection: endpoint queue, keyed membership, sorted nearest-key lookup or indexed editing. A container that performs one of those well can perform another poorly. Indexed traversal of a linked list can revisit the same chain for every position.
Then define lifetime and ownership. A copied membership snapshot differs from a backed view; both can still share mutable values. An immutable factory can reject nulls that an older caller previously stored, so migration needs data validation rather than a class-name swap.
Finally define concurrency and admission. A concurrent map does not bound distinct keys, and a fixed thread pool does not bound pending tasks. A service queue may need capacity, rejection, interruption and shutdown policies in addition to a FIFO order. None of these Java containers promises durable delivery after process loss.
