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.
Last updated: September 2026

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:

  1. java.lang.Iterable<T> $\rightarrow$ java.util.Collection<E>: The root hierarchy for element-based collections (List, Set, Queue, Deque).
  2. java.util.Map<K, V>: An independent root hierarchy representing key-value mappings (does not extend Collection or Iterable).

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: newCapacity=oldCapacity+(oldCapacity1)\text{newCapacity} = \text{oldCapacity} + (\text{oldCapacity} \gg 1)
  • Time Complexities:
    • $O(1)$ random access (get(i), set(i, val)). Implements the RandomAccess marker interface.
    • Amortized $O(1)$ append (add(val)).
    • $O(n)$ insertion or removal at arbitrary positions due to System.arraycopy element shifting.
  • Null Support: Fully permits null elements.

LinkedList<E>

  • Underlying Data Structure: Doubly-linked node chain (Node<E> with item, next, prev).
  • Dual Interface Implementation: Implements both List<E> and Deque<E>.
  • Time Complexities:
    • $O(1)$ insertion and removal at head and tail.
    • $O(n)$ indexed lookup (get(i) traverses from nearest end). Does not implement RandomAccess.
  • 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, and contains.
  • Requires stored elements to correctly implement consistent hashCode() and equals() 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 set size rather than capacity.

3. TreeSet<E>

  • Backed by a Red-Black self-balancing binary search tree (NavigableMap<E, Object>).
  • $O(\log n)$ time for add, remove, and contains.
  • Elements are ordered according to their natural ordering (Comparable) or an explicit Comparator.
  • Uniqueness Contract: Uniqueness is determined strictly by compareTo() or compare() returning 0, not by equals()!
  • Null Handling: Throws NullPointerException if null is 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 TypeThrows Exception on FailureReturns Special Value (false / null)
Insertadd(e) (throws IllegalStateException)offer(e) (returns false if full)
Removeremove() (throws NoSuchElementException)poll() (returns null if empty)
Examineelement() (throws NoSuchElementException)peek() (returns null if empty)

ArrayDeque<E> vs. LinkedList<E> vs. Legacy Stack

  • ArrayDeque uses a resizable circular array buffer.
  • Significantly faster than LinkedList for queue and stack operations due to memory locality and lack of node allocations.
  • Preferred over the legacy synchronized java.util.Stack.
  • Strict Null Rule: ArrayDeque strictly prohibits null elements, throwing NullPointerException on add(null) or offer(null).

PriorityQueue<E>

  • Implements an unbounded priority min-heap.
  • Elements are ordered according to natural order or a custom Comparator.
  • peek() and poll() always return the lowest (highest priority) element in $O(\log n)$ time.
  • Iteration Order: Iterating with for-each or iterator() does NOT guarantee sorted order (only root min-heap property is guaranteed).
  • Null Rule: Strictly prohibits null elements (throws NullPointerException).

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 = 8 and 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 = 6 during 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 null keys 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 / MapNull Elements / KeysNull ValuesNotes
ArrayList, LinkedListAllowedN/AAllows multiple nulls
HashSet, LinkedHashSetAllowed (1 null)N/AAt most one null
TreeSetProhibitedN/AThrows NullPointerException (natural order)
ArrayDeque, PriorityQueueProhibitedN/AThrows NullPointerException
HashMap, LinkedHashMapAllowed (1 null key)AllowedNull key placed in bucket 0
TreeMapProhibited (key)AllowedThrows NPE for null key (natural order)
Hashtable, ConcurrentHashMapProhibited (key)ProhibitedThrows NPE for null key or value
List.of, Set.of, Map.ofProhibitedProhibitedNull-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, and merge, if the remapping lambda returns null, 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:

  1. Truly Immutable: Calling mutating methods (add, remove, set, put) throws UnsupportedOperationException.
  2. Null-Hostile: Passing null elements or keys/values throws NullPointerException immediately.
  3. Duplicate-Hostile at Creation: Set.of("A", "A") or Map.of("K", 1, "K", 2) throws IllegalArgumentException at construction time!
  4. Randomized Iteration Order: Set.of and Map.of randomize iteration order across JVM runs to prevent reliance on order.
  5. Space-Efficient: Highly optimized internal representations consuming significantly less memory than ArrayList or HashSet.

Factories vs. Collections.unmodifiableList() Views

  • Collections.unmodifiableList(existingList): Creates an unmodifiable wrapper view around an existing collection. If the underlying existingList is mutated directly, the changes are visible through the unmodifiable view.
  • List.copyOf(existingList) (Java 10+): Creates a true independent unmodifiable copy. If existingList is already an unmodifiable collection created by List.of(), copyOf returns 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. Rejects null keys and values.
  • CopyOnWriteArrayList<E>: Thread-safe variant of ArrayList where all mutative operations (add, set, remove) are implemented by making a fresh copy of the underlying array. Iterators never throw ConcurrentModificationException and reflect the snapshot at the time the iterator was created. Ideal for read-heavy, write-rare scenarios (e.g., event listeners).
Loading diagram...
Java Collections Framework Core Class and Interface Hierarchy
Test Your Knowledge

What happens when the following Java statement is executed at runtime? Set<String> items = Set.of("Alpha", "Beta", "Alpha");

A
B
C
D
Test Your Knowledge

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?

A
B
C
D
Test Your Knowledge

Which of the following method calls on an empty ArrayDeque<String> will result in a NullPointerException?

A
B
C
D
Test Your Knowledge

Which collection implementation among the following provides O(1) indexed random access and implements the RandomAccess marker interface?

A
B
C
D