Java Collections Framework: Hierarchy and How to Choose
The Java collections framework in one map: List, Set, Queue and Map, their main classes, time complexities and null policies, and how to choose between them.
- Course: Java study plan
- Module: Collections framework
- Kind: Lesson
- Reading time: 14 min
- Runtime: OpenJDK 18
What is the Java collections framework?
The Java collections framework is the set of data-structure interfaces and classes in java.util. Interfaces — List, Set, Queue, Deque and Map — describe what a collection does; classes such as ArrayList, HashSet, HashMap and ArrayDeque decide how, and with it the performance and iteration order. All rely on equals and hashCode and compare by contents.
Lesson
java.util holds the data structures every Java program is built from: lists, sets, maps, queues. They share one design — interfaces that describe what a collection does, classes that decide how, and a small set of conventions (equals/hashCode, Iterable, fail-fast iterators, optional operations) that let them interoperate. This lesson is the map of the framework and the decision procedure for picking a structure; the following lessons take each family in depth.
The hierarchy
Iterable<E>
└── Collection<E> — size, isEmpty, contains, add, remove, iterator, stream, …
├── List<E> — ordered by index, duplicates allowed
│ ├── ArrayList — growable array; the default list
│ ├── LinkedList — doubly linked; also a Deque
│ └── (Vector, Stack) — legacy, synchronised; do not use
├── Set<E> — no duplicates (by equals)
│ ├── HashSet — hash table; no order
│ ├── LinkedHashSet — hash table + insertion order
│ └── TreeSet — red-black tree; sorted (SortedSet, NavigableSet)
└── Queue<E> — head-first processing
├── PriorityQueue — heap; smallest first
└── Deque<E> — both ends
├── ArrayDeque — the stack and queue of choice
└── LinkedList
Map<K, V> — NOT a Collection; keys → values, unique keys
├── HashMap — hash table; no order
├── LinkedHashMap — + insertion (or access) order
├── TreeMap — sorted by key (SortedMap, NavigableMap)
├── EnumMap — array indexed by enum ordinal (Module 10)
├── ConcurrentHashMap — thread-safe (Module 17)
└── (Hashtable) — legacy, synchronised; do not use
Map is separate from Collection because a map is not a bag of elements — but its views are collections: keySet() is a Set<K>, values() a Collection<V>, entrySet() a Set<Map.Entry<K, V>>.
Interfaces first
Declare with the interface, construct with the class:
List<String> names = new ArrayList<>();
Set<Integer> seen = new HashSet<>();
Map<String, List<Order>> byCustomer = new HashMap<>();
Deque<Character> stack = new ArrayDeque<>();
Queue<Task> queue = new ArrayDeque<>();
Method parameters and return types use the interfaces (List<String>, Collection<? extends T>); a public method returning ArrayList<String> promises an implementation detail forever. The one common exception is a private field where the concrete type's extra methods are needed (LinkedHashMap.removeEldestEntry, TreeMap.firstKey) — declare it as the narrowest interface that has them (NavigableMap).
Choosing a structure
| Need | Use | Why |
|---|---|---|
| A sequence, index access, appends | ArrayList | O(1) get/append; cache-friendly |
| A stack or queue | ArrayDeque | O(1) at both ends; faster than LinkedList, and Stack is legacy |
| Unique elements, fast membership | HashSet | O(1) contains |
| Unique, remember insertion order | LinkedHashSet | + predictable iteration |
| Unique, sorted, range queries | TreeSet | O(log n), first/floor/subSet |
| Key → value lookup | HashMap | O(1) |
| Key → value, insertion order or LRU | LinkedHashMap | order + removeEldestEntry |
| Key → value, sorted / nearest key | TreeMap | floorKey, headMap, ordered iteration |
| Enum keys or elements | EnumMap / EnumSet | array/bit-vector speed |
| Always-smallest-first processing | PriorityQueue | O(log n) insert and poll |
| Frequent inserts/removes in the middle by iterator | LinkedList | O(1) at the iterator — rarely the actual bottleneck |
| Shared across threads | ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue | Module 17 |
Default choices: ArrayList, HashMap, HashSet, ArrayDeque. Switch only when a measured or structural need appears (order, sorting, both-ends access).
Complexities to know cold
| Operation | ArrayList | LinkedList | HashSet/HashMap | TreeSet/TreeMap | ArrayDeque | PriorityQueue |
|---|---|---|---|---|---|---|
| get(i) / by key | O(1) | O(n) | O(1) avg | O(log n) | — | — |
| add at end / put | O(1) amortised | O(1) | O(1) avg | O(log n) | O(1) | O(log n) |
| add at front | O(n) | O(1) | — | — | O(1) | — |
| remove by index / key | O(n) | O(n) to find, O(1) to unlink | O(1) avg | O(log n) | O(1) at ends | O(log n) poll |
| contains | O(n) | O(n) | O(1) avg | O(log n) | O(n) | O(n) |
| iteration order | index | index | none | sorted | FIFO/LIFO | not sorted! |
"avg" for hash structures assumes a decent hashCode; the worst case degrades to O(n) (or O(log n) once buckets treeify, Java 8+).
The conventions every collection follows
equals/hashCodeon elements drivecontains,remove(Object), set membership and map keys — override them on element/key classes (Module 8) or use records.Iterable— every collection works with for-each andforEach; maps via their views.- Fail-fast iterators — modifying a collection while iterating it (other than through the iterator) throws
ConcurrentModificationException(lesson 7). - Optional operations — immutable collections throw
UnsupportedOperationExceptionfromadd/remove; the interface documents which methods are optional. - Null policy varies:
ArrayList/HashMap/HashSetallow nulls;TreeMap/TreeSetreject null keys (cannot compare);List.of/Map.of/ConcurrentHashMapreject nulls entirely. toStringprints contents ([a, b],{k=v}) — unlike arrays.equalsbetween collections is by contents: two lists with the same elements in order are equal; two sets with the same elements are equal, regardless of implementation class.
The utility classes
Collections (sort, reverse, shuffle, max, min, frequency, unmodifiableX, synchronizedX, emptyX, singletonX, nCopies) and Arrays (asList, sort, binarySearch, fill, copyOf, stream) hold the static helpers; List.of, Set.of, Map.of, List.copyOf (Java 9–10) create immutable collections (lesson 8).
Reading the API docs
Each interface's Javadoc specifies contracts (ordering, null policy, optional operations); each class's documents complexity and iteration order. ArrayList's says "constant amortized time" for add; HashMap's explains load factor; TreeMap's says "log(n) time cost for containsKey, get, put and remove". When choosing, read the class summary — it is written to answer exactly this question.
Interview angle
- "
ArrayListvsLinkedList?" Array-backed O(1) index access and cache locality vs linked nodes with O(1) insert/remove at a known position;ArrayListwins almost always in practice. - "
HashMapvsTreeMap?" O(1) unordered vs O(log n) sorted with navigation methods. - "Why is
Mapnot aCollection?" It maps keys to values rather than holding elements; its views are collections. - "Which structures reject nulls?"
TreeMap/TreeSet(keys/elements),List.of/Map.of/Set.of,ConcurrentHashMap,ArrayDeque. - "What should you declare a variable as?" The interface —
List, notArrayList.
Key takeaways
- Interfaces (
List,Set,Map,Queue,Deque) describe behaviour; classes (ArrayList,HashMap, …) decide performance and order. - Defaults:
ArrayList,HashMap,HashSet,ArrayDeque;Linked*for order,Tree*for sorting,PriorityQueuefor smallest-first. - Know the complexity table and the null policies.
- Elements need correct
equals/hashCode; collections compare by contents and print their contents.
Common questions
Why is Map not a Collection in Java?
A Map associates keys with values rather than holding a bag of elements, so it does not fit Collection's contract. Its views are collections, though: keySet() is a Set, values() a Collection and entrySet() a Set of Map.Entry.
Which Java collection should I use?
Start with the defaults: ArrayList for a sequence, HashMap for key-value lookup, HashSet for unique elements and ArrayDeque for a stack or queue. Switch to LinkedHashMap or LinkedHashSet for insertion order, TreeMap or TreeSet for sorting and range queries, and PriorityQueue for smallest-first processing.
Which Java collections do not allow null?
TreeMap and TreeSet reject null keys and elements because they cannot compare them; List.of, Set.of, Map.of, ConcurrentHashMap and ArrayDeque reject nulls entirely. ArrayList, HashMap and HashSet allow them.
Should you declare a variable as List or ArrayList?
Declare it with the interface — List<String> names = new ArrayList<>() — and use interfaces for parameters and return types too. A public method returning ArrayList promises that implementation forever; the interface leaves you free to change it.
What is the time complexity of HashMap, TreeMap and ArrayList operations?
HashMap and HashSet get, put and contains are O(1) on average; TreeMap and TreeSet operations are O(log n); ArrayList get is O(1) and append O(1) amortised, while contains and insertion at the front are O(n).
Exercises
Pick the structure
Read an integer n and n words. Using the right structure for each job, print: first=<first word> and last=<last word> (from a List), distinct=<count> (a HashSet), sorted=<distinct words in natural order, space-separated> (a TreeSet), inOrder=<distinct words in first-seen order> (a LinkedHashSet), and top=<the most frequent word; ties broken by natural order> (a HashMap of counts).
Example: 5 then b a b c a →
first=b last=a
distinct=3
sorted=a b c
inOrder=b a c
top=aChoose by workload
Encode the framework's decision table. Read n lines, each a workload described by flags: kind=<list|set|map|queue> plus zero or more of sorted, ordered (insertion order), lifo, priority. Print the default class for each: list → ArrayList; set → HashSet, LinkedHashSet if ordered, TreeSet if sorted; map → HashMap/LinkedHashMap/TreeMap likewise; queue → ArrayDeque, or PriorityQueue if priority (lifo is still ArrayDeque, used as a stack). sorted beats ordered when both appear.
Example: 3 then kind=set ordered, kind=map sorted, kind=queue priority →
LinkedHashSet
TreeMap
PriorityQueueIn this module: Collections framework
- The collections framework — the map and how to choose (this lesson)
- Lists — ArrayList, LinkedList and the List API
- Sets — HashSet, LinkedHashSet and TreeSet
- Maps — HashMap internals, TreeMap, LinkedHashMap and the modern API
- Queues, deques and PriorityQueue
- Sorting, Comparable and Comparator in depth
- Iterators, fail-fast behaviour and safe modification
- Immutable collections and the utility toolkit
- Checkpoint — Collections framework
← Checkpoint — Generics · Lists — ArrayList, LinkedList and the List API →