6.3 Core Collections: Lists, Sets, Queues, and Maps
Key Takeaways
- The Java Collections Framework organizes collections under Iterable<T> and Collection<E>, while Map<K, V> forms an independent root hierarchy.
- ArrayList provides O(1) indexed random access with a 1.5x dynamic growth factor, while LinkedList offers O(1) endpoint insertion/removal without RandomAccess support.
- Set implementations enforce uniqueness: HashSet relies on hashCode/equals, LinkedHashSet preserves encounter order, and TreeSet maintains sorted order via Comparable/Comparator.
- ArrayDeque provides faster, memory-efficient LIFO/FIFO operations than Stack or LinkedList and strictly rejects null elements.
- Unmodifiable factory methods (List.of, Set.of, Map.of) create truly immutable, null-hostile collections, differing fundamentally from unmodifiable view wrappers.
Core Collections: Lists, Sets, Queues, and Maps
The Java Collections Framework (JCF) provides a unified architecture for representing, organizing, and manipulating data collections. On the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) exam, questions assess your in-depth understanding of collection internal architectures, performance trade-offs, null acceptance rules, unmodifiable factories, and functional Map mutation operations.
1. JCF Architecture and Root Interfaces
The framework is structured into two main inheritance branches:
java.lang.Iterable<T>$\rightarrow$java.util.Collection<E>: The root hierarchy for element-based collections (List,Set,Queue,Deque).java.util.Map<K, V>: An independent root hierarchy representing key-value mappings (does not extendCollectionorIterable).
2. The List<E> Implementations: ArrayList vs. LinkedList
A List is an ordered collection (sequence) that permits duplicate elements and allows precise control over element insertion by integer index.
package java.util;
public interface List<E> extends Collection<E> {
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
List<E> subList(int fromIndex, int toIndex);
}
ArrayList<E>
- Underlying Data Structure: Dynamic resizable array (
Object[] elementData). - Initial Capacity: Default capacity is $10$ upon first element addition.
- Growth Formula: Grows by $50%$ ($1.5\times$) when capacity is exceeded:
- Time Complexities:
- $O(1)$ random access (
get(i),set(i, val)). Implements theRandomAccessmarker interface. - Amortized $O(1)$ append (
add(val)). - $O(n)$ insertion or removal at arbitrary positions due to
System.arraycopyelement shifting.
- $O(1)$ random access (
- Null Support: Fully permits
nullelements.
LinkedList<E>
- Underlying Data Structure: Doubly-linked node chain (
Node<E>withitem,next,prev). - Dual Interface Implementation: Implements both
List<E>andDeque<E>. - Time Complexities:
- $O(1)$ insertion and removal at head and tail.
- $O(n)$ indexed lookup (
get(i)traverses from nearest end). Does not implementRandomAccess.
- Memory Overhead: Higher memory footprint per element due to node object allocation and bidirectional pointers.
3. The Set<E> Implementations: HashSet, LinkedHashSet, and TreeSet
A Set is a Collection that contains no duplicate elements ($e_1.\text{equals}(e_2)$ is never true).
// Set implementations compared
Set<String> hashSet = new HashSet<>(); // Fast, no ordering guarantee
Set<String> linkedSet = new LinkedHashSet<>(); // Fast, maintains insertion encounter order
Set<String> treeSet = new TreeSet<>(); // Logarithmic, sorted by natural order or Comparator
1. HashSet<E>
- Backed internally by a
HashMap<E, Object>. - $O(1)$ average time for
add,remove, andcontains. - Requires stored elements to correctly implement consistent
hashCode()andequals()contracts. - Order: Makes no guarantees regarding iteration order; order can change across JVM executions or table rehashes.
2. LinkedHashSet<E>
- Extends
HashSet<E>while maintaining a doubly-linked list running through all entries. - Iteration occurs in insertion encounter order.
- Performance is nearly equal to
HashSet, with slightly faster iteration proportional to setsizerather thancapacity.
3. TreeSet<E>
- Backed by a Red-Black self-balancing binary search tree (
NavigableMap<E, Object>). - $O(\log n)$ time for
add,remove, andcontains. - Elements are ordered according to their natural ordering (
Comparable) or an explicitComparator. - Uniqueness Contract: Uniqueness is determined strictly by
compareTo()orcompare()returning0, not byequals()! - Null Handling: Throws
NullPointerExceptionifnullis added when using natural ordering.
4. The Queue<E> and Deque<E> Implementations
Queues represent collections designed for holding elements prior to processing, typically in FIFO (First-In, First-Out) or priority order. Deque (Double-Ended Queue) supports element insertion and removal at both endpoints (LIFO and FIFO).
Queue Method Matrix: Exception vs. Special Value
| Operation Type | Throws Exception on Failure | Returns Special Value (false / null) |
|---|---|---|
| Insert | add(e) (throws IllegalStateException) | offer(e) (returns false if full) |
| Remove | remove() (throws NoSuchElementException) | poll() (returns null if empty) |
| Examine | element() (throws NoSuchElementException) | peek() (returns null if empty) |
ArrayDeque<E> vs. LinkedList<E> vs. Legacy Stack
ArrayDequeuses a resizable circular array buffer.- Significantly faster than
LinkedListfor queue and stack operations due to memory locality and lack of node allocations. - Preferred over the legacy synchronized
java.util.Stack. - Strict Null Rule:
ArrayDequestrictly prohibitsnullelements, throwingNullPointerExceptiononadd(null)oroffer(null).
PriorityQueue<E>
- Implements an unbounded priority min-heap.
- Elements are ordered according to natural order or a custom
Comparator. peek()andpoll()always return the lowest (highest priority) element in $O(\log n)$ time.- Iteration Order: Iterating with
for-eachoriterator()does NOT guarantee sorted order (only root min-heap property is guaranteed). - Null Rule: Strictly prohibits
nullelements (throwsNullPointerException).
5. The Map<K, V> Implementations
Map maps unique keys to values. Keys cannot contain duplicates, and each key maps to at most one value.
HashMap<K, V> Internals & Treeification
- Bucket Table: Array of
Node<K, V>buckets. - Default Settings: Initial capacity = $16$, load factor = $0.75$. Threshold to resize = $16 \times 0.75 = 12$.
- Treeification (Java 8+): When collisions in a single bucket reach
TREEIFY_THRESHOLD = 8and total table capacity is at least $64$, the bucket linked list is converted to a Red-Black tree (TreeNode), reducing worst-case lookup from $O(n)$ to $O(\log n)$. - If capacity is $< 64$, the table resizes instead of treeifying.
- When bucket entries shrink to
UNTREEIFY_THRESHOLD = 6during resizing, the tree is converted back into a linked list.
LinkedHashMap<K, V>
- Maintains a doubly-linked list through all entries.
- Can maintain insertion order (default) or access order (for LRU caches when constructed with
new LinkedHashMap<>(cap, factor, true)).
TreeMap<K, V>
- Implements
NavigableMap<K, V>using a Red-Black tree. - Keys are sorted. Rejects
nullkeys when using natural ordering.
6. Null Acceptance Rules Across All Collections
Understanding null support across collections is one of the most frequently tested topics on the 1Z0-830 exam:
| Collection / Map | Null Elements / Keys | Null Values | Notes |
|---|---|---|---|
ArrayList, LinkedList | Allowed | N/A | Allows multiple nulls |
HashSet, LinkedHashSet | Allowed (1 null) | N/A | At most one null |
TreeSet | Prohibited | N/A | Throws NullPointerException (natural order) |
ArrayDeque, PriorityQueue | Prohibited | N/A | Throws NullPointerException |
HashMap, LinkedHashMap | Allowed (1 null key) | Allowed | Null key placed in bucket 0 |
TreeMap | Prohibited (key) | Allowed | Throws NPE for null key (natural order) |
Hashtable, ConcurrentHashMap | Prohibited (key) | Prohibited | Throws NPE for null key or value |
List.of, Set.of, Map.of | Prohibited | Prohibited | Null-hostile: Throws NPE |
7. Modern Map Functional Computation Methods
Java 8 introduced default methods on Map to perform atomic, concise key-value transformations:
Map<String, Integer> wordCounts = new HashMap<>();
// 1. getOrDefault: Returns fallback if key is absent
int count = wordCounts.getOrDefault("java", 0);
// 2. putIfAbsent: Inserts only if key is missing or mapped to null
wordCounts.putIfAbsent("java", 1);
// 3. computeIfAbsent: Computes value ONLY if key is absent or mapped to null
wordCounts.computeIfAbsent("python", key -> key.length()); // "python" -> 6
// 4. computeIfPresent: Recomputes ONLY if key is present and non-null
// If remapping function returns null, the entry is REMOVED from the map!
wordCounts.computeIfPresent("java", (k, v) -> v + 1); // "java" -> 2
wordCounts.computeIfPresent("python", (k, v) -> null); // REMOVES "python"!
// 5. compute: Computes new value regardless of presence
// If function returns null, existing entry is REMOVED
wordCounts.compute("ruby", (k, v) -> (v == null) ? 1 : v + 1);
// 6. merge: Essential for frequency counting / combining values
// If key absent -> sets value. If present -> applies remapping function.
// If remapping function returns null -> REMOVES entry!
wordCounts.merge("java", 10, (oldVal, newVal) -> oldVal + newVal); // 2 + 10 = 12
wordCounts.merge("scala", 5, Integer::sum); // "scala" absent -> sets to 5
[!IMPORTANT] Map Removal on Null: In
compute,computeIfPresent, andmerge, if the remapping lambda returnsnull, the key is removed from the map completely!
8. Unmodifiable Collection Factories vs. View Wrappers
Java 9 introduced convenient unmodifiable collection factory methods:
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("X", "Y", "Z");
Map<String, Integer> map = Map.of("K1", 1, "K2", 2);
Map<String, Integer> bigMap = Map.ofEntries(
Map.entry("A", 1),
Map.entry("B", 2)
);
Characteristics of List.of, Set.of, Map.of:
- Truly Immutable: Calling mutating methods (
add,remove,set,put) throwsUnsupportedOperationException. - Null-Hostile: Passing
nullelements or keys/values throwsNullPointerExceptionimmediately. - Duplicate-Hostile at Creation:
Set.of("A", "A")orMap.of("K", 1, "K", 2)throwsIllegalArgumentExceptionat construction time! - Randomized Iteration Order:
Set.ofandMap.ofrandomize iteration order across JVM runs to prevent reliance on order. - Space-Efficient: Highly optimized internal representations consuming significantly less memory than
ArrayListorHashSet.
Factories vs. Collections.unmodifiableList() Views
Collections.unmodifiableList(existingList): Creates an unmodifiable wrapper view around an existing collection. If the underlyingexistingListis mutated directly, the changes are visible through the unmodifiable view.List.copyOf(existingList)(Java 10+): Creates a true independent unmodifiable copy. IfexistingListis already an unmodifiable collection created byList.of(),copyOfreturns the original instance directly without copying.
9. Concurrent Collections Overview
Standard collections are not thread-safe. Java provides specialized concurrent implementations in java.util.concurrent:
ConcurrentHashMap<K, V>: Uses lock-striping and CAS (Compare-And-Swap) at the bucket node level. Allows concurrent reads without locking and highly concurrent writes. Rejectsnullkeys and values.CopyOnWriteArrayList<E>: Thread-safe variant ofArrayListwhere all mutative operations (add,set,remove) are implemented by making a fresh copy of the underlying array. Iterators never throwConcurrentModificationExceptionand reflect the snapshot at the time the iterator was created. Ideal for read-heavy, write-rare scenarios (e.g., event listeners).
What happens when the following Java statement is executed at runtime? Set<String> items = Set.of("Alpha", "Beta", "Alpha");
Consider the following code snippet: Map<String, Integer> map = new HashMap<>(); map.put("A", 10); map.computeIfPresent("A", (k, v) -> null); map.merge("B", 20, (oldV, newV) -> oldV + newV); map.merge("B", 5, (oldV, newV) -> null); What are the contents of map after execution?
Which of the following method calls on an empty ArrayDeque<String> will result in a NullPointerException?
Which collection implementation among the following provides O(1) indexed random access and implements the RandomAccess marker interface?