Choosing a collection
List, Set, Map, Queue and Deque, their main classes, what each operation costs, and the immutable versions.
Work out the main operation, then the order you need.
- Positions, in order →
ArrayList. - "Have I seen this?", no duplicates →
HashSet(TreeSetif it must stay sorted). - Look up a value by a key →
HashMap(TreeMapfor sorted keys,LinkedHashMapfor insertion order). - Oldest first, or newest first →
ArrayDequeas a queue (offer/poll) or a stack (push/pop). - Most urgent first →
PriorityQueue. - Never changes after it's built →
List.of,Set.of,Map.of.
Then check the costs: a contains on a list inside a loop is the classic hidden slowdown.
The interfaces
Section
The collections framework
Collection, List, Set, Queue and Map, and why you declare the interface type.
Section
List and ArrayList
Positions, duplicates allowed.
Section
Sets
No duplicates: HashSet, LinkedHashSet, TreeSet.
Section
Maps
Keys to values: HashMap, LinkedHashMap, TreeMap.
ArrayDeque both ways, and PriorityQueue.
Costs and the choice
Formal. With n elements: ArrayList.get(i), set(i, x) and
add(x) (amortized) are O(1); add(0, x), remove(0) and
contains(x) are O(n). LinkedList.get(i) is O(n); adding or removing
at either end is O(1). HashMap.get, put and containsKey, and
HashSet.add and contains, are O(1) on average. TreeMap and
TreeSet operations are O(log n). PriorityQueue.peek is O(1);
offer and poll are O(log n).
In plain English. Jumping to a numbered slot or looking up a key in a hash table takes the same time however big the collection is. Searching a list checks every item, so it grows with the list. A sorted tree takes a few more steps each time the data doubles, about 20 steps for a million items.
Example. Checking a million IDs with list.contains(id) inside a
loop over another million IDs is quadratic: about a trillion steps.
Putting the IDs in a HashSet first makes each check constant and the
whole loop linear.
Why this rule exists. The costs follow from how each class stores
its elements: an array for ArrayList, a chain of nodes for
LinkedList, buckets chosen by hashCode for HashMap, a balanced tree
for TreeMap.
What get, contains and lookups cost in each class.
The same cost at any size.
Section
Choosing a collection
Big-O in plain words, how the classes work inside, and a procedure for choosing.
Read-only collections
List.of, copyOf, unmodifiable views, and first/last on sequenced collections.