Collections
HashMap internals, List/Set/Map trade-offs, fail-fast iterators, concurrent and immutable collections.
How does HashMap work internally?
An array of buckets (Node[] table). put(k, v):
hash = k.hashCode()spread withh ^ (h >>> 16).- Index =
hash & (capacity - 1)(capacity is a power of two). - Empty bucket → new node. Otherwise walk the bucket: same hash and
equals→ replace value; else append. - A bucket with 8+ nodes is converted to a red-black tree (if capacity ≥ 64), giving O(log n) worst case.
- When
size > capacity × 0.75, the table doubles; each node stays atior moves toi + oldCap.
get repeats steps 1–3. That’s why equals and hashCode must be consistent and keys should be immutable.
Why is the default load factor 0.75?
It’s a trade-off between memory and collision probability. Lower values waste space with mostly-empty buckets; higher values make buckets longer and lookups slower. At 0.75 the expected bucket length stays very small, while about a quarter of the table is unused.
What happens if you use a mutable object as a HashMap key and then change it?
If a field used in hashCode changes, the entry stays in the bucket for its old hash. get with the mutated key computes a new hash and looks in the wrong bucket — the entry becomes unreachable (effectively leaked) though it still counts in size(). Use immutable keys: String, boxed types, records with immutable components.
HashMap vs Hashtable vs ConcurrentHashMap vs Collections.synchronizedMap?
| Thread-safe | Nulls | Locking | |
|---|---|---|---|
HashMap |
No | 1 null key, null values | — |
Hashtable |
Yes (legacy) | No | Every method synchronised |
Collections.synchronizedMap |
Yes | As wrapped map | One lock for the whole map |
ConcurrentHashMap |
Yes | No | CAS + per-bucket locks; lock-free reads |
Use ConcurrentHashMap for shared maps.
Why doesn't ConcurrentHashMap allow null keys or values?
In a concurrent map, get(key) == null must unambiguously mean “absent”. With nulls you couldn’t distinguish “absent” from “mapped to null” without a separate containsKey call — and another thread could change the map between the two calls. Disallowing nulls removes that race.
ArrayList vs LinkedList — which would you choose and why?
Almost always ArrayList: O(1) random access, contiguous memory (cache-friendly), low per-element overhead. LinkedList has O(1) insert/remove at a known node, but finding the node is O(n), each element is a separate object, and iteration is slow. For queues and stacks use ArrayDeque.
HashSet vs LinkedHashSet vs TreeSet?
HashSet (backed by a HashMap) has no order, O(1). LinkedHashSet keeps insertion order. TreeSet keeps elements sorted (red-black tree, O(log n)) with navigation methods like floor and ceiling. TreeSet uses compareTo, not equals, to detect duplicates.
What is a fail-fast iterator? How do you remove elements while iterating?
Fail-fast iterators track a modCount; if the collection is structurally modified outside the iterator, the next next() throws ConcurrentModificationException — a best-effort bug detector, not a thread-safety guarantee.
Remove safely with iterator.remove() or collection.removeIf(predicate). Concurrent collections have weakly consistent iterators that never throw CME.
How would you implement an LRU cache in Java?
Extend LinkedHashMap with access order and override removeEldestEntry:
class Lru<K, V> extends LinkedHashMap<K, V> {
private final int max;
Lru(int max) { super(16, 0.75f, true); this.max = max; }
@Override protected boolean removeEldestEntry(Map.Entry<K, V> e) { return size() > max; }
}In production prefer Caffeine (W-TinyLFU eviction, TTLs, stats). In a whiteboard round you may be asked for a HashMap + doubly linked list with O(1) get/put.
List.of vs Arrays.asList vs Collections.unmodifiableList?
List.of(...)— truly immutable, rejects nulls.Arrays.asList(array)— fixed-size view:setwrites through to the array,add/removethrow.Collections.unmodifiableList(list)— read-only view: changes to the underlying list show through.List.copyOf(c)— independent immutable copy.
What are Sequenced Collections (Java 21)?
SequencedCollection, SequencedSet and SequencedMap give ordered collections a uniform API: getFirst(), getLast(), addFirst(), addLast(), removeFirst(), removeLast() and a live reversed() view — implemented by List, Deque, LinkedHashSet, SortedSet, LinkedHashMap and SortedMap.
When would you use a PriorityQueue? What is its complexity?
For repeatedly taking the smallest (or largest) element: scheduling, Dijkstra, merging sorted streams, top-K. It’s a binary heap: offer/poll O(log n), peek O(1), contains O(n). Iteration order is not sorted. For top-K largest, keep a min-heap of size K — O(n log K).
Why is EnumMap faster than HashMap for enum keys?
EnumMap is backed by an array indexed by ordinal() — no hashing, no collisions, no node objects, iteration in declaration order. EnumSet is a bit vector, so set operations are single CPU instructions.
What is the time complexity of common operations on TreeMap?
get, put, remove, containsKey, firstKey, floorKey, ceilingKey are O(log n) (red-black tree). Iteration is O(n) in key order. Range views (headMap, tailMap, subMap) are live views.
No questions match these filters.