Collections Framework

Choosing the Right Collection

A decision guide: match the collection to the questions your code asks. Default to ArrayList, HashMap, HashSet, ArrayDeque — and deviate only for ordering, navigation, priorities, enums, or concurrency.
  • Ask: duplicates? ordering? key-lookup? both-ends access? priority? concurrent?
  • Defaults: ArrayList / HashMap / HashSet / ArrayDeque
  • Need sorted iteration or nearest-key queries → TreeMap/TreeSet
  • Need insertion order remembered → LinkedHashMap/LinkedHashSet
  • Enum keys/elements → EnumMap/EnumSet, always
  • Multithreaded → Concurrent Collections, never synchronizedX wrappers by reflex
Decision table
You need…Reach forWhy
Indexed access, a sequenceArrayListcontiguous, cache-friendly, O(1) get — see Lists
Stack or FIFO queueArrayDequecircular array; beats Stack & LinkedList — Queues Deques
Dedup, don't care about orderHashSetO(1) contains — see Sets
Dedup, keep insertion orderLinkedHashSethash speed + stable iteration order
Key → value lookupHashMapO(1) get/put — see Maps
Sorted iteration, range/nearest-key queriesTreeMap / TreeSetred-black tree, NavigableXxx API — Sorted Collections
Deterministic iteration order, no sorting neededLinkedHashMap / LinkedHashSetlinked entries preserve insertion order
LRU cacheLinkedHashMap in access-order mode + removeEldestEntryaccess reorders to most-recent; the hook evicts the eldest past capacity
Priority / always-process-minPriorityQueuebinary heap, poll is O(log n)
Enum keys / elementsEnumMap / EnumSetarray/bit-vector speed (EJ 36–37) — Enums
Shared across threadsConcurrentHashMap, CopyOnWriteArrayList, blocking queuessee Concurrent Collections

The performance literature's framing: choose by access pattern first, asymptotics second, constants third. An O(1) structure with terrible cache behavior can lose to an O(n) scan for small n — and most collections are small. Measure before optimizing (Performance Methodology); but don't write the accidental O(n²) either.

Sizing and immutability defaults
// Known size → presize (avoids regrowth copies and rehashing):
List<Row> rows = new ArrayList<>(rowCount);
Map<String, User> byId = HashMap.newHashMap(userCount);   // Java 19+

// Fixed reference data → immutable factories:
static final Set<String> VOWELS = Set.of("a", "e", "i", "o", "u");
Sources
  • Core Java, Volume I: Fundamentals (13th ed.)Ch. 9 — Collections
  • Optimizing JavaCh. 11 — Java Language Performance Techniques
  • Java Secrets: High Performance and ScalabilityPerformance chapters