Does Map extend Collection? No. You use keySet(), values() and entrySet() views.
Is Collection the same as Collections? No. Collections is a utility class with static helpers.
#hierarchy#interfaces
Q2
What is the difference between ArrayList and LinkedList?
basic
ArrayList is backed by a resizable array: O(1) random access, amortized O(1) append, O(n) insert/remove in the middle. LinkedList is a doubly linked list: O(1) insert/remove at a known node or the ends, but O(n) access by index.
In practice ArrayList wins almost always: contiguous memory is cache friendly and each LinkedList node costs ~24 extra bytes (header + prev + next + item reference).
LinkedList implements Deque too, but ArrayDeque is usually faster for that role.
⚠ Follow-up traps
Is removing in the middle of a LinkedList O(1)? Only if you already hold the node/iterator position. Finding it by index is O(n).
Is LinkedList.get(i) fast near the ends? It walks from the nearer end, so it is O(min(i, n-i)), still O(n) overall.
#arraylist#linkedlist#complexity
Q3
How does ArrayList grow internally?
basic
The default constructor starts with an empty shared array and allocates capacity 10 on first add. When full it grows to old + (old >> 1), i.e. 1.5x, by copying with Arrays.copyOf.
Use new ArrayList<>(n) or ensureCapacity when the size is known to avoid repeated copying.
trimToSize() releases unused slots.
⚠ Follow-up traps
Is the initial capacity 10 at construction? No, it is lazy (Java 8+); new ArrayList<>(0) and the default both start empty.
Does remove shrink the array? No, capacity never shrinks automatically.
#arraylist#capacity
Q4
Explain how HashMap works internally.
basic
HashMap keeps an array of buckets (Node<K,V>[] table). The key's hashCode() is spread, masked to an index, and the entry is stored in that bucket as a linked list (or a red-black tree when large). Lookup compares hash then equals.
Index = (n - 1) & hash where n is a power of two.
Spread function: h ^ (h >>> 16) mixes high bits into low bits.
Default capacity 16, load factor 0.75.
Allows one null key and many null values; not thread-safe.
⚠ Follow-up traps
Why is capacity always a power of two? So the index is a cheap bitmask instead of a modulo, and resize can split buckets without rehashing.
Which is compared first, equals or hash? Stored hash first (cheap), then reference ==, then equals.
#hashmap#internals
Q5
What is the load factor and when does HashMap resize?
basic
Resize happens when size > threshold, where threshold = capacity * loadFactor (12 for the default 16 x 0.75). The table doubles and entries are redistributed.
Higher load factor saves memory but increases collisions; lower speeds lookups but wastes memory.
Resize is O(n) and happens on the writing thread.
⚠ Follow-up traps
When does resize trigger exactly, at the 12th or 13th put? On the 13th insertion, because the check is ++size > threshold.
Does the table ever shrink? No.
#hashmap#resize#load-factor
Q6
How does resizing work in Java 8 HashMap and what changed from Java 7?
intermediate
Because capacity doubles, each entry either stays at index i or moves to i + oldCap, decided by one bit: (hash & oldCap) == 0. Java 8 splits each bucket into a "lo" and "hi" list preserving relative order.
Java 7 re-inserted nodes at the head of the new bucket, which reversed order and could create a cycle (infinite loop) when two threads resized concurrently.
Java 8 preserves order, so the classic cyclic-list hang is gone, but concurrent use is still unsafe (lost updates, corrupted tree).
Java 8 also appends new nodes at the tail and adds treeification.
⚠ Follow-up traps
Does Java 8 make HashMap thread-safe enough to share? No; data loss and inconsistent state are still possible.
Is rehashing needed on resize? No, the stored full hash is reused; only one extra bit is examined.
#hashmap#java8#resize
Q7
What is treeification in HashMap?
intermediate
When a single bucket reaches TREEIFY_THRESHOLD = 8 nodes and the table has at least MIN_TREEIFY_CAPACITY = 64 slots, the list becomes a red-black tree, bounding worst-case lookup at O(log n) instead of O(n).
If the table is smaller than 64, HashMap resizes instead of treeifying.
Trees untreeify when they shrink to UNTREEIFY_THRESHOLD = 6 (during resize split/removal).
Tree ordering uses hashCode, then Comparable if the keys implement it, then a tie-break by identity hash; non-comparable keys make lookups in a tree bucket slower.
⚠ Follow-up traps
Does 8 colliding entries always produce a tree? No, only with table capacity >= 64.
Why 8 and 6 rather than the same number? Hysteresis avoids flip-flopping between structures.
#hashmap#treeify#java8
Q8
Why must keys be immutable, and what is the equals/hashCode contract?
basic
Equal objects must return equal hash codes; hash code must be stable while the object is a key. If a field used in hashCode changes after insertion, the entry sits in the wrong bucket and becomes unreachable.
Override both together; use the same fields in both.
Unequal objects may share a hash code (collisions are legal, just slow).
⚠ Follow-up traps
If I override only equals, what breaks? Hash-based collections may treat equal objects as different, since identity hash is used.
Can hashCode return a constant? Legal but degrades to O(n) (O(log n) for comparable keys with treeification).
#equals#hashcode#contract
Q9
How does HashSet work?
basic
HashSet wraps a HashMap; elements are the keys and every value is a shared dummy object PRESENT. add returns true if map.put(e, PRESENT) == null.
Same complexity and resize behaviour as HashMap.
Allows one null; iteration order is unspecified.
⚠ Follow-up traps
What does add return for a duplicate?false, and the existing element is not replaced.
Does HashSet copy the element? No, it stores the reference.
#hashset#internals
Q10
HashSet vs LinkedHashSet vs TreeSet.
basic
HashSet: no order, O(1). LinkedHashSet: insertion order, O(1), extra memory for a linked list. TreeSet: sorted order by Comparable/Comparator, O(log n), backed by a TreeMap.
TreeSet uses compareTo/compare for equality, not equals.
Does re-adding an element change LinkedHashSet order? No, insertion order is not affected by re-insertion.
Can a TreeSet contain two objects that are not equals? No, if compare returns 0 they are duplicates.
#set#ordering
Q11
HashMap vs LinkedHashMap vs TreeMap vs Hashtable.
basic
HashMap: unordered, O(1), nulls allowed. LinkedHashMap: insertion (or access) order, O(1). TreeMap: sorted by key, O(log n), no null keys with natural ordering. Hashtable: legacy, synchronized on every method, no nulls.
For thread safety use ConcurrentHashMap, not Hashtable or synchronizedMap for high contention.
⚠ Follow-up traps
Why does Hashtable reject nulls? It calls key.hashCode() and value.equals directly, and ambiguity of null results was avoided by design (same reason ConcurrentHashMap bans nulls).
Is Hashtable fully deprecated? Not formally, but it is obsolete and should not be used.
#map#comparison
Q12
How does LinkedHashMap support access order and an LRU cache?
intermediate
Construct with accessOrder = true so get/put move the entry to the tail; override removeEldestEntry to evict the head when size exceeds a limit.
Is iterating while calling get safe in access-order mode? No, get is a structural modification and throws ConcurrentModificationException.
#linkedhashmap#lru
Q13
How does TreeMap work and what are its guarantees?
intermediate
TreeMap is a red-black tree implementing NavigableMap. get, put, remove, containsKey are O(log n); keys are ordered by Comparable or a supplied Comparator.
Key equality is defined by compare == 0, so an inconsistent comparator violates the Map contract.
Not synchronized; ConcurrentSkipListMap is the concurrent sorted alternative.
⚠ Follow-up traps
Can TreeMap hold a null key? Not with natural ordering (NPE); a custom comparator may allow it.
Are subMap results copies? No, they are live views backed by the original map.
#treemap#red-black-tree
Q14
When should you use EnumMap and EnumSet?
intermediate
Use them whenever keys/elements are of one enum type. EnumMap is an array indexed by ordinal(), EnumSet is a bit vector (RegularEnumSet for <= 64 constants, a long[] otherwise).
Faster and smaller than HashMap/HashSet; iteration follows enum declaration order.
Null keys are rejected; not thread-safe.
Iterators are weakly consistent (no ConcurrentModificationException).
⚠ Follow-up traps
Why should you not use ordinal() yourself? It is brittle if constants are reordered; EnumMap hides it.
Can you create an EnumSet with new? No, only via factories like noneOf, allOf, of, range.
#enummap#enumset
Q15
How does PriorityQueue work?
intermediate
PriorityQueue is an array-backed binary min-heap. offer/poll are O(log n), peek is O(1), remove(Object) and contains are O(n).
Ordering from Comparable or Comparator; head is the least element.
Iteration and toString do not return sorted order, only heap array order.
Not thread-safe (PriorityBlockingQueue is); no null elements; not stable for equal priorities.
Building from a collection uses O(n) heapify.
⚠ Follow-up traps
How do you get a max-heap?new PriorityQueue<>(Comparator.reverseOrder()).
How to preserve FIFO among equal priorities? Add a monotonically increasing sequence number to the comparison.
#priorityqueue#heap
Q16
ArrayDeque vs LinkedList vs Stack for stack/queue usage.
intermediate
Prefer ArrayDeque for both stack (push/pop) and queue (offer/poll) use: it is a resizable circular array, faster than LinkedList and without the Vector synchronization of legacy Stack.
ArrayDeque rejects null (null is the empty sentinel for poll/peek); LinkedList allows it.
Capacity is always a power of two; no index access.
Stack extends Vector, is synchronized and exposes list operations that break LIFO discipline.
⚠ Follow-up traps
What does pop do on an empty ArrayDeque? Throws NoSuchElementException; poll/pollFirst returns null.
Is ArrayDeque thread-safe? No; use ConcurrentLinkedDeque or LinkedBlockingDeque.
#arraydeque#deque#stack
Q17
What are the Queue method families (add/offer, remove/poll, element/peek)?
basic
Each operation has a throwing and a non-throwing form: add/offer, remove/poll, element/peek. Throwing forms raise IllegalStateException (full) or NoSuchElementException (empty); the others return false or null.
For bounded queues, offer returns false when full; blocking queues add put/take and timed offer/poll.
⚠ Follow-up traps
Why avoid null elements in queues?poll() returning null becomes ambiguous.
Which form to use in bounded producer/consumer?offer with timeout or put, based on desired back-pressure.
#queue#api
Q18
What is the difference between fail-fast and fail-safe iterators?
intermediate
Fail-fast iterators (ArrayList, HashMap, HashSet) check modCount and throw ConcurrentModificationException on detected structural change. "Fail-safe" (more precisely weakly consistent or snapshot) iterators never throw it.
CopyOnWriteArrayList: iterator works on an immutable snapshot, never sees later changes.
ConcurrentHashMap: weakly consistent, may or may not reflect updates made after creation.
Fail-fast is best effort, not a guarantee; do not rely on it for correctness.
⚠ Follow-up traps
Does fail-fast mean thread-safe detection? No, it is a debugging aid, not guaranteed under races.
Do fail-safe iterators support remove? Snapshot iterators of CopyOnWriteArrayList throw UnsupportedOperationException on remove.
#iterator#fail-fast#fail-safe
Q19
What causes ConcurrentModificationException and how do you avoid it?
basic
The iterator's expected modCount differs from the collection's after a structural change made outside the iterator (add/remove during a for-each). Avoid it with Iterator.remove(), removeIf, collecting items to remove first, or a concurrent collection.
list.removeIf(s -> s.isEmpty()); // preferredfor (Iterator<String> it = list.iterator(); it.hasNext();) if (it.next().isEmpty()) it.remove(); // also safe
⚠ Follow-up traps
Is a single-threaded program immune? No, the classic case is single-threaded.
Is set(i, x) on an ArrayList during iteration a CME? No, it is not structural.
#cme#iterator
Q20
Explain Comparable vs Comparator.
basic
Comparable<T> defines the natural ordering inside the class (compareTo). Comparator<T> is an external, pluggable ordering (compare), so a type can have many.
compareTo should be consistent with equals (strongly recommended), especially for TreeSet/TreeMap.
⚠ Follow-up traps
Why not return a - b in a comparator? Integer overflow gives wrong sign; use Integer.compare.
How to sort nulls last?Comparator.nullsLast(...).
#comparable#comparator
Q21
What does "consistent with equals" mean for compareTo?
intermediate
compare(a, b) == 0 iff a.equals(b). When violated, sorted collections use the comparator for identity, so they behave differently from hash-based collections.
BigDecimal("1.0") and BigDecimal("1.00") are not equals but compareTo == 0: a TreeSet keeps one, a HashSet keeps both.
⚠ Follow-up traps
Is it illegal to be inconsistent? No, but it must be documented.
Is Double natural ordering consistent with ==? No; -0.0 < 0.0 and NaN equals itself in compareTo.
#comparable#treeset#equals
Q22
Is Collections.sort / List.sort stable? Which algorithm?
intermediate
Yes for object sorting: List.sort, Collections.sort, and Arrays.sort(T[], Comparator) use TimSort (stable merge/insertion hybrid, O(n log n), near O(n) on presorted data). Arrays.sort(int[]) uses dual-pivot quicksort, which is not stable (stability is irrelevant for primitives).
Stability allows multi-key sorting by sorting on the minor key first.
Stream.sorted() is stable for ordered streams.
⚠ Follow-up traps
Can TimSort throw? Yes, IllegalArgumentException: Comparison method violates its general contract! for inconsistent comparators.
Is PriorityQueue stable? No.
#sorting#stability
Q23
What is the difference between unmodifiable, immutable and synchronized collection wrappers?
intermediate
Collections.unmodifiableList(l) is a read-only view: changes to the backing list show through. List.copyOf / List.of are truly immutable (no backing, no mutators). Both are shallow: elements themselves can be mutable.
Collections.synchronizedList wraps every method with a mutex; iteration still needs manual synchronized (list).
Immutable factories (Java 9+) reject null.
⚠ Follow-up traps
Is Collections.unmodifiableList safe to publish? Only if nobody keeps a reference to the backing list.
Does List.copyOf(list) always copy? No, if the argument is already an immutable List.of result it returns the same instance.
#immutable#unmodifiable
Q24
How do List.of, Set.of and Map.of behave?
intermediate
They return compact immutable collections: mutators throw UnsupportedOperationException, nulls throw NullPointerException, Set.of/Map.of throw IllegalArgumentException on duplicates, and Set/Map iteration order is unspecified and varies per JVM run (randomized salt).
Map.of supports up to 10 pairs; use Map.ofEntries(Map.entry(...)) for more.
contains(null) on a List.of throws NPE, unlike ArrayList.
⚠ Follow-up traps
Is Arrays.asList immutable? No, fixed-size: set works, add/remove throw, and writes go through to the array.
Can iteration order of Set.of be relied on? No, it changes between runs.
#immutable#java9#factories
Q25
What does Arrays.asList return and what are the traps?
basic
A fixed-size List view over the array (Arrays$ArrayList). set writes through to the array; add and remove throw UnsupportedOperationException.
Arrays.asList(int[]) yields List<int[]> of size 1, since primitives do not autobox into varargs.
Wrap with new ArrayList<>(Arrays.asList(...)) for a growable copy.
⚠ Follow-up traps
Does changing the array alter the list? Yes, they share storage.
Arrays.asList(1,2,3).size() vs Arrays.asList(new int[]{1,2,3}).size()? 3 vs 1.
#arrays#aslist
Q26
Why does subList require care?
intermediate
subList(from, to) is a live view of the parent. Writes go through both ways; structurally modifying the parent afterwards makes the view throw ConcurrentModificationException on next use.
Idiom: list.subList(a, b).clear() removes a range efficiently.
A long-lived subList retains the whole parent (memory leak); copy with new ArrayList<>(list.subList(a, b)).
⚠ Follow-up traps
Is subList O(n) to create? No, O(1) view creation.
Is String.substring the same kind of view? No; since Java 7u6 it copies.
#sublist#views
Q27
What are Collections utility methods you should know?
emptyList() and singletonList() return immutable shared instances.
binarySearch on an unsorted list gives undefined results; on LinkedList it degrades to O(n) steps.
⚠ Follow-up traps
What does binarySearch return if absent?-(insertionPoint) - 1.
Is Collections.shuffle deterministic? Only with a seeded Random.
#collections#utilities
Q28
Time complexity of common collection operations.
intermediate
Average costs:
ArrayList: get O(1), add end O(1) amortized, add/remove middle O(n), contains O(n).
LinkedList: get O(n), add/remove ends O(1), contains O(n).
HashMap/HashSet: get/put/contains O(1) average, O(log n) worst case once a bucket is treeified (O(n) only for a long chain below the treeify threshold).
Is HashMap.get truly O(1)? Amortized average assuming good hashing; iteration is O(capacity + size).
Is size() O(1) for all? Yes for the standard ones (ConcurrentLinkedQueue.size() is O(n)).
#complexity#big-o
Q29
How much memory do collections use? Compare boxed collections to arrays.
advanced
Collections store references, so List<Integer> costs about 4-8 bytes per slot (compressed oops) plus 16 bytes per Integer object outside the cache, versus 4 bytes for int[].
HashMap.Node is ~32 bytes (header 12, hash 4, key, value, next refs, aligned) on top of the table slot; HashMap<Integer,Integer> is roughly 70+ bytes per entry including boxed key/value.
TreeMap.Entry is ~40 bytes; LinkedList.Node ~24 bytes.
Does ArrayList waste memory? Up to ~33% spare capacity after growth; use trimToSize for long-lived lists.
Are Valhalla value types available? Not in a released Java baseline here; do not assume it.
#memory#boxing
Q30
How should you size a HashMap for N expected entries?
intermediate
Pass an initial capacity of ceil(N / 0.75) so no resize occurs. new HashMap<>(N) is wrong because it resizes once N exceeds 0.75*N rounded to a power of two.
int cap = (int) Math.ceil(n / 0.75);Map<String, Integer> m = new HashMap<>(cap);// Java 19+: HashMap.newHashMap(n)
The constructor rounds capacity up to the next power of two via tableSizeFor.
The table is allocated lazily on first put.
⚠ Follow-up traps
What does new HashMap<>(100) actually allocate? 128 slots, threshold 96.
Is there a helper?HashMap.newHashMap(int) and HashSet.newHashSet(int) since Java 19.
#capacity#hashmap
Q31
What does hashCode of String, List and records look like, and how do you write a good one?
intermediate
String.hashCode is s[0]*31^(n-1) + ... + s[n-1] (cached). List.hashCode combines element hashes the same 31-based way. Use Objects.hash(a, b) (allocates a varargs array) or let a record generate equals/hashCode/toString.
record Point(int x, int y) {}Set<Point> s = new HashSet<>(List.of(new Point(1, 2)));s.contains(new Point(1, 2)); // true
⚠ Follow-up traps
Is a record's hash code specified exactly? No, only that it is consistent with equals.
Why 31? An odd prime; 31*i == (i << 5) - i is cheap to compute.
#hashcode#records
Q32
What is the difference between Iterator and ListIterator, and Iterable vs Iterator?
Why not Collections.synchronizedMap everywhere? Single lock, compound actions (check-then-act) still need external locking.
Is Vector thread-safe for iteration? Individual calls yes; iteration with modification still throws CME.
#concurrent#thread-safety
Q34
How does ConcurrentHashMap work in Java 8+ versus Java 7?
advanced
Java 7 used 16 lock-striped Segments (each a ReentrantLock over a mini hash table). Java 8+ removed segments: an empty bucket is filled with a lock-free CAS; otherwise it uses synchronized on the bucket's first node. Resizing is cooperative (multiple threads migrate bins), and bins treeify like HashMap.
Reads are lock-free (volatile fields); size() uses striped CounterCells (like LongAdder), so it is an estimate under concurrency.
No null keys or values.
⚠ Follow-up traps
Is if (!m.containsKey(k)) m.put(k, v) safe? No, use putIfAbsent/computeIfAbsent.
Can computeIfAbsent call other map operations in its function? No; it can deadlock or throw IllegalStateException (recursive update).
#concurrenthashmap#internals
Q35
How does CopyOnWriteArrayList work and what are its costs?
intermediate
Each mutation copies the backing array under a lock and publishes it via a volatile reference; reads and iterators use the array snapshot without locking.
Mutation O(n) time and memory; excellent for many readers and rare writers (listener lists).
Iterators never throw CME but may show stale data and do not support remove.
⚠ Follow-up traps
Is addIfAbsent atomic? Yes.
Good for a write-heavy log buffer? No; each add copies the whole array.
#copyonwrite#concurrent
Q36
Explain BlockingQueue implementations and their differences.
intermediate
ArrayBlockingQueue: bounded, one lock, array. LinkedBlockingQueue: optionally bounded (default Integer.MAX_VALUE), separate put/take locks, higher throughput. PriorityBlockingQueue: unbounded heap. SynchronousQueue: zero capacity hand-off. DelayQueue: elements available after a delay. LinkedTransferQueue: transfer waits for consumer.
Unbounded queues can cause OutOfMemoryError when producers outpace consumers.
Executors.newFixedThreadPool uses an unbounded LinkedBlockingQueue; newCachedThreadPool uses SynchronousQueue.
⚠ Follow-up traps
Which gives back-pressure? A bounded queue with blocking put or offer with timeout.
Does LinkedBlockingQueue.size() take a lock? No, it reads an AtomicInteger.
#blockingqueue#producer-consumer
Q37
What are sequenced collections in Java 21?
intermediate
JEP 431 adds SequencedCollection, SequencedSet, SequencedMap with a defined encounter order and uniform methods: getFirst, getLast, addFirst, addLast, removeFirst, removeLast, and reversed() (a live reversed view).
List, Deque, LinkedHashSet, SortedSet (TreeSet) are sequenced; LinkedHashMap and SortedMap implement SequencedMap (firstEntry, lastEntry, pollFirstEntry, putFirst, putLast, sequencedKeySet...).
HashSet/HashMap are not sequenced.
⚠ Follow-up traps
What does getFirst() do on an empty list? Throws NoSuchElementException (previously list.get(0) threw IndexOutOfBoundsException).
What does addFirst do on TreeSet?UnsupportedOperationException; order is by comparator.
#java21#sequenced
Q38
Is List.reversed() a copy?
intermediate
No, it is a live view. Changes to the original appear in the reversed view and vice versa (for modifiable lists). Copy explicitly when a snapshot is needed.
List<Integer> l = new ArrayList<>(List.of(1, 2, 3));List<Integer> r = l.reversed();l.add(4);System.out.println(r); // [4, 3, 2, 1]
⚠ Follow-up traps
Before Java 21, how to reverse in place?Collections.reverse(list) (mutates) or iterate descendingIterator.
Does reversed() on List.of allow writes? No, it stays immutable.
#java21#sequenced#views
Q39
Difference between Iterator order for HashMap and why HashMap order is not guaranteed.
basic
Iteration walks the table from index 0 up, each bucket in chain/tree-next order, so order depends on hash values, capacity and insertion history. It can change after a resize or between JVM versions.
⚠ Follow-up traps
Small Integer keys often iterate sorted; is that guaranteed? No, it is an artifact of hash(i) == i and a large enough table.
Which map gives predictable order?LinkedHashMap or TreeMap.
#hashmap#ordering
Q40
How do Map.computeIfAbsent, merge, compute, getOrDefault and putIfAbsent differ?
intermediate
getOrDefault(k, d): read only, does not insert.
putIfAbsent(k, v): inserts if absent or mapped to null; returns the old value (eagerly evaluated v).
computeIfAbsent(k, f): lazy value creation; inserts the result unless null; returns the current value.
merge(k, v, f): inserts v if absent, else f(old, v); a null result removes the key.
compute(k, f): full control, null result removes.
Map<String, List<String>> g = new HashMap<>();g.computeIfAbsent("a", k -> new ArrayList<>()).add("x");Map<String, Integer> c = new HashMap<>();for (String w : words) c.merge(w, 1, Integer::sum);
⚠ Follow-up traps
Can the mapping function modify the same HashMap? No; Java 9+ HashMap detects it and throws ConcurrentModificationException.
Is merge atomic on ConcurrentHashMap? Yes, per key.
#map#java8#api
Q41
What is IdentityHashMap, WeakHashMap and when are they used?
advanced
IdentityHashMap compares keys with == and uses System.identityHashCode (graph traversal, serialization, proxies). WeakHashMap holds keys via weak references; entries vanish after the key is garbage collected (canonicalizing caches, metadata).
A WeakHashMap whose value strongly references its own key never gets cleared.
Do not use interned strings, boxed small ints or class literals as WeakHashMap keys expecting eviction.
⚠ Follow-up traps
Does IdentityHashMap follow the Map contract? Intentionally violates equals-based semantics.
Is WeakHashMap a good cache? Not for LRU/size control; use Caffeine or soft/expiry-based caches.
#identityhashmap#weakhashmap
Q42
What is the difference between keySet(), values() and entrySet() and which should you iterate?
basic
All three are live views of the map. Iterate entrySet() when you need both key and value: it avoids a lookup per key (keySet() + get), which matters for TreeMap (O(log n) per lookup).
Removing via the view (keySet().remove, values().removeIf, entrySet().removeIf) removes from the map.
add is unsupported on the views.
⚠ Follow-up traps
Can you reuse a Map.Entry after iteration? Don't store it for HashMap guarantees; entry.setValue writes through, and entries from Map.entry() are immutable.
Is map.keySet() a Set copy? No, a view.
#map#iteration
Q43
What is the difference between Set.equals/hashCode and List.equals/hashCode?
intermediate
List.equals compares element by element in order. Set.equals compares membership regardless of order and implementation; Set.hashCode is the sum of element hashes. Map.equals compares entry sets.
new ArrayList<>(List.of(1,2)).equals(new LinkedList<>(List.of(1,2))) is true.
A List never equals a Set, even with the same elements.
⚠ Follow-up traps
Is HashSet.equals(TreeSet) possible? Yes, if same elements (comparator caveats).
Danger of using a mutable collection as a map key? Its hash changes when contents change.
#equals#set#list
Q44
How does removing from a list by index vs by object work (remove(int) vs remove(Object))?
basic
List<Integer>.remove(1) calls remove(int index) and removes the element at index 1; remove(Integer.valueOf(1)) removes the first element equal to 1.
⚠ Follow-up traps
What does list.remove((Integer) 1) do? Removes by value.
Cost of ArrayList.remove(0)? O(n) due to shifting (System.arraycopy).
#list#overloading#autoboxing
Q45
What are the generics rules relevant to collections (PECS, raw types)?
intermediate
List<Integer> is not a List<Number> (generics are invariant). Use ? extends T to read (producer) and ? super T to write (consumer): Producer Extends, Consumer Super.
Raw types skip type checks and permit heap pollution that fails later with ClassCastException.
Collections.checkedList can enforce types at runtime.
⚠ Follow-up traps
Can you add to List<? extends Number>? Only null.
Are arrays covariant? Yes, which is why ArrayStoreException exists; generics fixed it at compile time.
#generics#pecs
Q46
What is the difference between Collection.toArray() variants?
intermediate
toArray() returns Object[]. toArray(new String[0]) returns a typed array (a new one if the supplied array is too small). Java 11 adds toArray(IntFunction), e.g. list.toArray(String[]::new).
new String[0] is as fast or faster than presizing on modern JVMs.
List.of(...).toArray() copies, so the result is mutable.
⚠ Follow-up traps
Does (String[]) list.toArray() work? No, ClassCastException.
If the passed array is larger than the list? The element after the last is set to null.
Stream.toList() (Java 16) returns an unmodifiable list and permits nulls; Collectors.toList() returns an unspecified, typically ArrayList. Collectors.toMap throws IllegalStateException on duplicate keys unless a merge function is given, and rejects null values.
Order of groupingBy output? A HashMap by default; pass a TreeMap::new supplier for ordering.
Is Collectors.toUnmodifiableList() the same as Stream.toList()? Similar, but it rejects nulls.
#streams#collectors
Q48
What is ConcurrentSkipListMap and when to choose it over TreeMap?
advanced
A lock-free, sorted, concurrent NavigableMap built on a probabilistic skip list: O(log n) expected for get/put/remove, with weakly consistent iterators. Choose it when multiple threads need sorted access without a global lock.
size() is O(n).
For single-threaded use TreeMap has lower overhead.
⚠ Follow-up traps
Does it permit null? No keys or values.
Is TreeMap synchronized via a wrapper equivalent? Wrappers block all readers on a single lock.
#skiplist#concurrent
Q49
How do Collections.synchronizedList and iteration interact?
intermediate
Individual methods are synchronized on the wrapper, but iteration and compound actions are not atomic; hold the wrapper's lock for the whole traversal.
List<String> l = Collections.synchronizedList(new ArrayList<>());synchronized (l) { for (String s : l) process(s);}
⚠ Follow-up traps
Does stream() hold the lock? No, you must synchronize manually.
Which lock object is used? The wrapper itself (mutex = this).
#synchronized#wrappers
Q50
What are weakly consistent iterators and what does the Javadoc guarantee?
advanced
Concurrent collections' iterators traverse elements as they existed at (or after) creation, never throw CME, and may or may not reflect later updates. Each element is returned at most once.
Bulk operations (putAll, forEach, size) are not atomic snapshots in ConcurrentHashMap.
⚠ Follow-up traps
Can an element appear twice? No.
Is isEmpty() followed by get safe? No, state may change in between.
#iterator#concurrent
Q51
What are the guarantees and gotchas of Collections.emptyList and Collections.singletonList vs List.of?
basic
emptyList()/singletonList() are immutable singletons that permit null (singleton) and accept contains(null). List.of() rejects null elements and throws on contains(null).
⚠ Follow-up traps
Is Collections.emptyList() safe to return from a method? Yes, immutable and shared.
Can you modify it? No, UnsupportedOperationException (including add of nothing: addAll(empty) is allowed).
#immutable#collections
Q52
What are Spliterator and why do collections implement it?
advanced
Spliterator traverses and partitions elements, enabling parallel streams. Collections report characteristics (ORDERED, SIZED, SUBSIZED, SORTED, DISTINCT, IMMUTABLE) and split quality.
ArrayList splits evenly (excellent for parallel); LinkedList splits poorly; HashSet is decent; TreeSet splits by tree structure.
⚠ Follow-up traps
Why are parallel streams on LinkedList slow? No cheap midpoint split.
What does SIZED give? Exact estimateSize, letting pipelines presize outputs.
#spliterator#streams
Scenarios
Q53
What happens when this loop runs?
basic
Throws ConcurrentModificationException on the next next() call after the removal. Use l.removeIf(s -> s.equals("a")).
⚠ Follow-up traps
What if the removed element is "b" (second to last)? No exception: after removal size == cursor, so hasNext() is false and the loop ends silently, printing [a, c].
What if it is the last element? CME, since hasNext() is still true (cursor != size).
#cme#iterator
Q54
A mutable object is used as a HashMap key. What happens?
intermediate
Prints null null 1. The entry is stored in the bucket for hash 1; get(k) now looks in bucket 2, and get(new Key(1)) finds the bucket but equals fails because the stored key has id 2. The entry is leaked and unreachable but still counted.
⚠ Follow-up traps
Can you remove it? Not via get/remove by key; only iteration (entrySet().removeIf) or clear().
Do String keys have this problem? No, they are immutable.
#mutable-key#hashcode
Q55
What is printed?
basic
Almost always 2. hashCode is not overridden, so the two equal objects usually land in different buckets and equals is never consulted. Override both.
⚠ Follow-up traps
Could it print 1? Rarely, if identity hashes happen to collide into the same bucket with equal full hash, which is practically never.
What if only hashCode is overridden? Equal hashes but equals is identity, so size is still 2.
#equals#hashset
Q56
Why does this `TreeSet` drop elements?
intermediate
Prints [Java] (List.of is iterated in order, so the first wins). The comparator returns 0 for case-variants, so TreeSet treats them as duplicates. A HashSet would keep all three.
⚠ Follow-up traps
Which instance remains on duplicate add? The existing one; the new one is discarded.
Does contains("JAVA") return true? Yes, compare-based lookup.
#treeset#comparator
Q57
What is the output of Arrays.asList manipulation?
basic
Prints [z, w] [z, w], then add throws UnsupportedOperationException. The list is a fixed-size write-through view of the array.
⚠ Follow-up traps
How to get independent growable list?new ArrayList<>(Arrays.asList(a)).
Does l.remove("x") work? No, same exception.
#aslist#views
Q58
A method returns Collections.unmodifiableList(items) and the caller still sees changes. Why?
intermediate
The wrapper is a view; the owner keeps mutating items, and the changes appear through the wrapper. Return List.copyOf(items) for a snapshot, or keep the owner's list private and never hand out the reference.
List<String> view = Collections.unmodifiableList(items);items.add("new");System.out.println(view.size()); // includes "new"
⚠ Follow-up traps
Is List.copyOf deep? No, element objects remain shared.
Cost of copying per call? O(n) each time; cache an immutable snapshot if reads are frequent.
#unmodifiable#defensive-copy
Q59
Why does Map.of("a", 1, "a", 2) fail, and what about nulls?
basic
Duplicate keys throw IllegalArgumentException: duplicate key: a at creation. Any null key or value throws NullPointerException. Use HashMap + Collections.unmodifiableMap if nulls are needed.
⚠ Follow-up traps
Does Map.of().get(null) work? It throws NPE.
Is Map.copyOf allowed with duplicates? A map cannot have them, so the question is moot; nulls throw.
#immutable#map-of
Q60
What does this print about modCount behavior in HashMap?
intermediate
No exception; prints 3. put on an existing key replaces the value and is not a structural modification (no modCount change). Adding a new key during iteration would throw CME.
⚠ Follow-up traps
What about m.put("d", 4) inside the loop?ConcurrentModificationException on the next iteration step.
What about ConcurrentHashMap there? No exception; the new key may or may not be visited.
#hashmap#cme
Q61
A HashMap in a multi-threaded service occasionally loses entries. Diagnose.
intermediate
HashMap is not thread-safe: concurrent puts can overwrite the same bucket slot (lost update), size goes out of sync, and concurrent resize can produce missing entries (Java 8) or an infinite loop (Java 7). Use ConcurrentHashMap (and atomic compound methods), or confine the map to one thread.
⚠ Follow-up traps
Does Collections.synchronizedMap fix check-then-act? No, if (!m.containsKey) m.put still races.
Does volatile on the field help? It publishes the reference only, not the contents.
#thread-safety#hashmap
Q62
Counter with ConcurrentHashMap: which implementation is correct?
intermediate
Only B is atomic. A is read-modify-write across two calls, so concurrent increments are lost. B executes the remapping atomically per key. For very hot keys, use ConcurrentHashMap<K, LongAdder> with computeIfAbsent(k, x -> new LongAdder()).increment().
⚠ Follow-up traps
Should the merge function be quick? Yes, it runs while holding the bin lock; avoid blocking or touching the same map.
Is getOrDefault itself thread-safe? Yes, but the sequence is not.
#concurrenthashmap#atomicity
Q63
Sorting stability bug: sort people by age then by name.
intermediate
Because List.sort is stable, you can sort by the secondary key first, then by the primary key and equal-primary items keep secondary order. Simpler and safer: one chained comparator.
list.sort(Comparator.comparing(Person::name));list.sort(Comparator.comparingInt(Person::age)); // stable: ties stay name-sorted// or:list.sort(Comparator.comparingInt(Person::age).thenComparing(Person::name));
⚠ Follow-up traps
Does this trick work with PriorityQueue? No, not stable.
Does parallelStream().sorted() stay stable? Yes for ordered streams, unordered() removes the guarantee.
#sorting#stability
Q64
A comparator uses subtraction and sorts incorrectly. Why?
intermediate
Prints [1, -2147483648] (wrong order). MIN_VALUE - 1 overflows to a positive number, so MIN_VALUE appears greater. Use Integer.compare(x, y) or Comparator.naturalOrder().
⚠ Follow-up traps
Can a broken comparator crash the sort? TimSort may throw "Comparison method violates its general contract".
Is Double.compare needed for doubles? Yes, and it handles NaN and -0.0.
#comparator#overflow
Q65
What happens when you put null into various collections?
Why does ConcurrentHashMap ban nulls?get returning null would be ambiguous between absent and null value in a concurrent setting.
TreeSet.add(null) on an empty set in Java 7+? NPE (compare is called).
#null#collections
Q66
A LRU cache built with LinkedHashMap evicts the wrong entries. Find the bug.
intermediate
Prints [2, 3]: insertion-order mode ignores the get(1), so the eldest (1) is evicted. Pass true as the third constructor argument for access order, which would yield [1, 3].
⚠ Follow-up traps
Is this safe across threads? No; even get mutates the structure in access-order mode.
When is removeEldestEntry called? After put, putIfAbsent, computeIfAbsent, merge.
#lru#linkedhashmap
Q67
Choose a structure: top K largest elements from a stream of N numbers.
intermediate
Keep a min-heap of size K: for each element, offer; if size exceeds K, poll the smallest. Time O(N log K), memory O(K), versus O(N log N) for sorting everything.
PriorityQueue<Integer> pq = new PriorityQueue<>();for (int x : data) { pq.offer(x); if (pq.size() > k) pq.poll(); }
⚠ Follow-up traps
Why min-heap for largest? The root is the smallest of the top K, the first candidate to evict.
Order of the final result? Heap iteration is unsorted; poll repeatedly or sort.
#priorityqueue#design
Q68
PriorityQueue iteration shows an unsorted order. Is it broken?
basic
1 is the head, but toString prints the internal array, e.g. [1, 2, 4, 5, 3], not sorted. Only poll() yields sorted order.
⚠ Follow-up traps
Does forEach give sorted order? No.
How to get a sorted snapshot?new ArrayList<>(pq) then sort, or poll into a list.
#priorityqueue#iteration
Q69
Implement a stack and queue: which class and what breaks with null?
basic
Prints 2 1 (push adds to the head), then push(null) throws NullPointerException. ArrayDeque forbids nulls.
⚠ Follow-up traps
Iteration order of this stack? Head to tail, i.e. most recent first, unlike the legacy Stack.
Use LinkedList to allow null? Possible, but null makes poll/peek ambiguous.
#arraydeque#stack
Q70
HashMap initialized with new HashMap<>(1000) for 1000 entries: does it resize?
advanced
No. 1000 rounds up to 1024, threshold 768; inserting the 769th entry triggers a resize to 2048. Correct presizing is ceil(1000 / 0.75) = 1334 -> 2048 capacity, or HashMap.newHashMap(1000) on Java 19+.
⚠ Follow-up traps
Memory impact of the oversized table? 2048 slots x 4 bytes (compressed oops) plus entries; acceptable versus a copy during growth.
Does a HashSet(1000) behave the same? Yes.
#capacity#hashmap
Q71
Bad hashCode: what is the impact?
intermediate
Every key lands in one bucket. Lookups cost O(n) with a chain (K is not Comparable), and once the bucket has 8+ nodes and table >= 64 it treeifies, but without Comparable the tree falls back to identity-hash tie-breaks and lookups must search both subtrees, so performance is still poor. Add Comparable to help trees, but fix the hash.
⚠ Follow-up traps
Is it functionally correct? Yes, only slow (and a DoS vector).
Why did Java 8 treeify at all? To bound damage from collisions or attacks (hash flooding).
#hashcode#performance
Q72
What does Set.of iteration print across runs?
basic
Order is unspecified and can differ between JVM runs because immutable sets/maps use a per-VM randomized salt. Never depend on it; use LinkedHashSet or List.of for stable order, or TreeSet.
⚠ Follow-up traps
Does List.of have the same issue? No, it keeps argument order.
Why randomize? To stop code from depending on incidental order.
#set-of#ordering
Q73
toMap collector throws at runtime. Why?
intermediate
IllegalStateException: Duplicate key a (attempted merging values apple and avocado). Supply a merge function (x, y) -> x, or use groupingBy to collect lists.
⚠ Follow-up traps
What if a value is null? NPE from HashMap.merge.
Does toMap preserve order? No, it returns a HashMap; pass a LinkedHashMap::new supplier.
#collectors#tomap
Q74
Why does this remove the wrong element?
basic
Prints [10, 30, 1]: remove(int index) is chosen over remove(Object), so index 1 (value 20) is removed. Use l.remove(Integer.valueOf(1)) to remove by value.
⚠ Follow-up traps
Same issue with Set<Integer>.remove(1)? No, Set has only remove(Object).
With List<Long> and remove(1)? Index removal still, since 1 is an int literal.
#autoboxing#list
Q75
sublist modification: what is the output?
intermediate
Throws ConcurrentModificationException: the parent was structurally modified after the view was created. Modifying through the view (s.add, s.clear()) is allowed and affects the parent.
⚠ Follow-up traps
What does s.clear() do first? Removes elements 2 and 3 from l.
Safe fix? Create the sublist after modifications or copy it.
#sublist#cme
Q76
Memory leak: a long-lived static map keeps growing. What are the common causes and fixes?
advanced
Unbounded caches keyed by request-scoped data, listeners never removed, and ThreadLocal/class-keyed maps hold strong references. Fixes: bounded LRU (LinkedHashMap.removeEldestEntry, Caffeine with maximumSize and expiry), WeakHashMap for lifecycle-bound metadata, explicit removal on lifecycle end, and metrics on map size.
⚠ Follow-up traps
Does WeakHashMap fix value->key reference cycles? No, the value strongly referencing the key prevents collection.
Does HashMap shrink after removes? No, the table stays large; create a new map.
#memory-leak#cache
Q77
Choose between ArrayList and LinkedList for a queue with frequent remove(0).
intermediate
Neither; use ArrayDeque. ArrayList.remove(0) is O(n) shifting. LinkedList is O(1) but with heavy per-node overhead and poor locality. ArrayDeque.poll() is O(1) on a circular array.
⚠ Follow-up traps
When is LinkedList justified? Almost never; maybe when removing via iterator in the middle during large single-pass edits, and even then removeIf on ArrayList is usually faster.
Does ArrayDeque support indexed access? No.
#design#arraylist#linkedlist
Q78
Why does Collections.binarySearch return a weird result?
intermediate
The list is not sorted, so the result is undefined (here it may return -5 or a wrong index). Sort first, and use the same comparator for sort and search. For a missing key the result is -(insertionPoint) - 1.
⚠ Follow-up traps
What does -1 mean? Not found and would insert at index 0.
Is it fast on LinkedList? Comparisons are O(log n) but traversal makes it O(n).
#binarysearch#sorting
Q79
Duplicated elements in a TreeMap with an inconsistent comparator: what happens?
advanced
Prints {aa=2}. Both keys compare equal (length 2), so the second put replaces the value but keeps the original key. Add a tie-breaker: .thenComparing(Comparator.naturalOrder()).
⚠ Follow-up traps
Does containsKey("zz") return true? Yes, it compares equal by length.
Is this a bug in TreeMap? No, it is the documented behaviour of a comparator inconsistent with equals.
#treemap#comparator
Q80
Reverse a list in Java 21: what are the three options and differences?
intermediate
Collections.reverse(list) mutates in place; list.reversed() gives a live view with no copying; new ArrayList<>(list.reversed()) makes a reversed copy.
List<Integer> l = new ArrayList<>(List.of(1, 2, 3));for (int x : l.reversed()) System.out.print(x); // 321, l unchanged
⚠ Follow-up traps
Does reversed() work on a HashSet? Not available; no encounter order.
Is Stream.sorted().reversed() valid? No, Stream has no reversed; use Comparator.reversed().
#java21#reverse
Q81
What is the result of getFirst/getLast on collections in Java 21?
basic
Prints NoSuchElementException. getFirst/getLast/removeFirst/removeLast throw it on empty sequenced collections, unlike get(0), which throws IndexOutOfBoundsException. Use isEmpty() guards or Deque.peekFirst for null-returning variants.
⚠ Follow-up traps
Does LinkedHashMap.firstEntry() return null if empty? Yes.
Does getFirst() work on List.of()? Yes, NoSuchElementException if empty.
#java21#sequenced
Q82
Sequenced map: what does putFirst do on LinkedHashMap with an existing key?
advanced
Prints {b=3, a=1}. putFirst inserts or repositions the key at the start and updates the value, unlike put where re-inserting does not change position (insertion order mode). TreeMap.putFirst throws UnsupportedOperationException.
⚠ Follow-up traps
Does put("a", 5) move a? No, in insertion-order mode position is unchanged.
Does m.reversed() copy? No, live view.
#java21#linkedhashmap
Q83
A stream produces a list that later throws UnsupportedOperationException. Why?
basic
Stream.toList() (Java 16+) returns an unmodifiable list, so add throws UnsupportedOperationException. Use collect(Collectors.toCollection(ArrayList::new)) when a mutable list is needed.
⚠ Follow-up traps
Does it allow nulls? Yes, unlike List.of.
Does Collectors.toList() guarantee mutability? No, the spec does not promise it, though today it is an ArrayList.
#streams#immutable
Q84
computeIfAbsent recursion: why does Fibonacci memoization blow up?
advanced
Since Java 9, HashMap.computeIfAbsent throws ConcurrentModificationException when the mapping function modifies the map (the recursive calls insert entries). On ConcurrentHashMap it can livelock or throw IllegalStateException: Recursive update. Check with get, compute, then put.
⚠ Follow-up traps
Did Java 8 throw? It silently corrupted or double-inserted, which is why Java 9 added the check.
Safer alternative? Explicit Long v = memo.get(n); if (v == null) {...}.
#computeifabsent#recursion
Q85
Which is correct for iterating a map and removing entries?
intermediate
Use map.entrySet().removeIf(e -> cond) or map.values().removeIf(...), or an explicit Iterator.remove(). Calling map.remove(key) inside a for-each over the map throws CME (except ConcurrentHashMap).
⚠ Follow-up traps
Does keySet().remove(k) during iteration throw? Yes, unless done through the iterator.
map.keySet().removeAll(...) with a List argument? O(n*m) when the argument's contains is linear; pass a Set.
#map#removal
Q86
What does equals do between ArrayList and Arrays.asList and why does assertEquals sometimes fail?
intermediate
List.equals compares elements in order regardless of implementation, so new ArrayList<>(List.of(1,2)).equals(Arrays.asList(1,2)) is true. assertEquals(List, Set) fails because a List never equals a Set, and array equals is identity: use Arrays.equals or assertArrayEquals.
⚠ Follow-up traps
new int[]{1}.equals(new int[]{1})?false.
Objects.equals(list, set) with same elements?false.
#equals#list
Q87
Multi-threaded counter on a HashMap<String, Integer> produces wrong totals. Fix it.
intermediate
Replace with ConcurrentHashMap + merge(k, 1, Integer::sum) or LongAdder values. Alternatives: partition per thread and merge at the end (no contention), or Collectors.groupingByConcurrent / counting in a parallel stream.
⚠ Follow-up traps
Is ConcurrentHashMap<String,Integer> plus map.put(k, map.get(k)+1) fine? No, still racy and NPE if absent.
Fastest for extremely hot single keys?LongAdder reduces CAS contention versus AtomicLong.
#concurrency#counter
Q88
CopyOnWriteArrayList used for a high-frequency event buffer causes latency spikes. Why?
intermediate
Each add copies the whole array (O(n) time and garbage), and writes serialize under a lock. Under heavy writes it floods the GC. Use ConcurrentLinkedQueue, a BlockingQueue, or a ring buffer; reserve COW for read-mostly data such as listener lists.
⚠ Follow-up traps
Why is iteration safe there? It uses the array snapshot captured at iterator creation.
Can batching writes help? Yes, addAll copies once.
#copyonwrite#performance
Q89
A HashMap with Integer keys: how does bucket placement work for key=17 in a 16-slot table?
advanced
Integer.hashCode() is the value, 17; spread 17 ^ (17 >>> 16) = 17; index (16 - 1) & 17 = 1. So 1 and 17 collide in bucket 1 at capacity 16, and after resizing to 32, 17 moves to index 17 (1 + oldCap) because 17 & 16 != 0.
⚠ Follow-up traps
Why h ^ (h >>> 16)? Otherwise only the low bits would influence the index for small tables, so keys differing only in high bits collide.
Does HashMap call hashCode again on resize? No, the hash is stored in the node.
#hashmap#hashing
Q90
EnumMap vs HashMap: what is the iteration order and null behavior here?
intermediate
Prints {MON=m, WED=w} (declaration order, not insertion order), then put(null, ...) throws NullPointerException. get(null) just returns null.
⚠ Follow-up traps
Can EnumMap take a null value? Yes.
Why must the constructor receive Day.class? To know the key universe and allocate the array.
#enummap#ordering
Q91
Pick the right collection: de-duplicate while preserving first-seen order.
basic
LinkedHashSet. new LinkedHashSet<>(list) then new ArrayList<>(set) removes duplicates preserving first occurrence; stream().distinct() also preserves encounter order for ordered streams.
⚠ Follow-up traps
What is the cost? O(n) time, extra memory for the set.
Does TreeSet fit? It sorts, which changes order.
#design#linkedhashset
Q92
Choose a structure for a leaderboard (ranked top scores, updates, rank queries).
advanced
For single-JVM, TreeMap/TreeSet keyed by (score desc, id) gives O(log n) update and range reads (headMap, descendingMap); rank by position is O(n) in a TreeSet, so use an order-statistic tree or Redis ZSET at scale. For concurrency use ConcurrentSkipListMap.
⚠ Follow-up traps
Updating a score? Remove old entry then add new; mutating the key in place corrupts the tree.
Same-score players? Include a unique tiebreaker in the comparator or one disappears.
#design#treemap#skiplist
Q93
What does the following print for a TreeMap range view?
intermediate
{1=v1, 2=v2} {3=v3, 4=v4, 5=v5} null 4. headMap excludes the bound, tailMap includes it by default, floorKey(0) has no key <= 0 so returns null, ceilingKey(4) is 4.
⚠ Follow-up traps
Include the upper bound?headMap(3, true).
What if you put into headMap(3) a key 7?IllegalArgumentException: key out of range.
#treemap#navigable
Q94
What are the pitfalls of removing during Stream.forEach over a collection?
intermediate
Modifying the source during a terminal operation is interference: ArrayList.forEach or stream().forEach(l::remove) throws CME (detected at the end of traversal for ArrayList's spliterator). Collect first and remove, or use removeIf.
⚠ Follow-up traps
Is it safe with CopyOnWriteArrayList? Yes, it iterates a snapshot.
Behavior on parallel streams? Undefined; races and wrong results.
#streams#cme
Q95
Shared mutable default: a getter returns the internal list. What are the risks?
basic
Callers can mutate internal state, break invariants, and cause CME while the owner iterates. Return an unmodifiable view, List.copyOf, or a stream/iterator. Also copy on the way in (constructor argument) because the caller keeps the reference.
class Order { private final List<Item> items; Order(List<Item> in) { this.items = List.copyOf(in); } List<Item> items() { return items; }}
⚠ Follow-up traps
Is List.copyOf enough if Item is mutable? No, deep immutability is needed.
Does unmodifiableList(in) in the constructor protect? No, the caller can still change in.
#encapsulation#defensive-copy
Q96
What is the difference in outcome between these two initializations?
basic
Both contain [x], but a is an anonymous subclass of ArrayList (double-brace initialization): an extra class per site, an implicit reference to the enclosing instance (memory leak if the list escapes), and getClass() is not ArrayList, which breaks equals-by-class checks and serialization. Prefer b.
⚠ Follow-up traps
Does a.equals(b) hold? Yes, List.equals is value-based.
Serialization risk? The anonymous class captures the outer this, which must also be serializable.
#double-brace#anonymous-class
Q97
PriorityQueue with a custom class: nothing sorts and a ClassCastException appears. Why?
basic
The second add throws ClassCastException: Task cannot be cast to class java.lang.Comparable; the first add succeeds (Java 7+ checks only when comparing). Implement Comparable<Task> or pass a Comparator.
⚠ Follow-up traps
Does a single-element add fail on TreeSet? Java 7+ calls compare(key, key), so it throws even for the first element.
Comparator throws NPE on null field? Use Comparator.nullsFirst.
#priorityqueue#comparable
Q98
Large HashMap iteration is slow despite few entries. Why?
advanced
HashMap iteration is O(capacity + size). A map that once held millions of entries and was emptied via remove/clear keeps its giant table, so iterating scans every slot. clear() also does not shrink it. Create a new HashMap (or let the old one be GC'd) instead of reusing.
⚠ Follow-up traps
Does LinkedHashMap have the same cost? No, iteration follows the linked list, O(size).
What if the map was oversized by presizing? Same slow iteration.
#hashmap#iteration#capacity
Q99
A ConcurrentHashMap size() call returns a value, but then the map changes. What can you rely on?
advanced
size() and isEmpty() are estimates under concurrent updates; they are exact only in quiescent state. Use mappingCount() for a long count and do not use size() for control flow decisions such as "if empty then put".
⚠ Follow-up traps
Is size() == 0 then put atomic? No, use putIfAbsent.
Max size in int?size() clamps at Integer.MAX_VALUE; mappingCount() does not.
#concurrenthashmap#size
Q100
What is printed after this null-safe grouping?
intermediate
{1=2, 2=2}. The TreeMap factory gives sorted keys, and counting() yields Long values. groupingBy throws NPE if the classifier returns null for an element.
⚠ Follow-up traps
Type of the values?Long, not Integer.
How to count into Integer?Collectors.summingInt(x -> 1).
#collectors#groupingby
Q101
What happens with Collections.sort on a list that contains null?
basic
Natural-order sorting throws NullPointerException when compareTo is called on null. Use list.sort(Comparator.nullsFirst(Comparator.naturalOrder())) (or nullsLast).
⚠ Follow-up traps
What if the list has a single null? No comparison is made, so no exception.
TreeMap with that comparator? Allows a null key.
#sorting#null
Q102
Which iteration approach is fastest for an ArrayList and a LinkedList?
intermediate
For ArrayList, indexed loop and iterator are similar. For LinkedList, never loop with get(i): it is O(n^2) overall. Use the iterator or for-each, O(n). RandomAccess marker interface tells algorithms which to use.
for (int i = 0; i < linked.size(); i++) linked.get(i); // O(n^2) trap
⚠ Follow-up traps
Which lists implement RandomAccess?ArrayList, Vector, CopyOnWriteArrayList, Arrays.asList; not LinkedList.
Does for-each box primitives in List<Integer>? It unboxes on assignment to int, allocation was at insertion.
#iteration#performance
Q103
How do you implement a thread-safe bounded producer-consumer with minimal code?
intermediate
Use ArrayBlockingQueue (or LinkedBlockingQueue(capacity)); producers put (block when full), consumers take (block when empty). Shut down with a poison pill or interrupt.
Why not LinkedBlockingQueue() without a bound? Unbounded memory growth under slow consumers.
Does take respond to interruption? Yes, throws InterruptedException.
#blockingqueue#design
Q104
HashSet of arrays or of List: what goes wrong?
intermediate
false. Arrays use identity equals/hashCode. Wrap values in a List<Integer>, a record, or Arrays.hashCode in a custom key class. A List key works but must never be mutated after insertion.
⚠ Follow-up traps
Set<List<Integer>> and then list.add(3)? The hash changes and the entry is lost in the wrong bucket.
Arrays.asList(1,2).hashCode() equals List.of(1,2).hashCode()? Yes, specified by List.hashCode.
#arrays#hashset#keys
Q105
Capacity planning: a service caches 5 million Long->String entries in a HashMap. What should you check?
advanced
Estimate about 100+ bytes per entry (table slot, Node 32, boxed Long 16-24, String + byte[] ~50+), so roughly 0.5-1 GB. Presize to avoid copy spikes (a resize needs old and new tables briefly), consider primitive maps (fastutil Long2ObjectOpenHashMap), bounded eviction, and off-heap or Redis if too large; measure with a heap dump or JOL.
⚠ Follow-up traps
Why does a resize cause latency spikes? O(n) redistribution on one thread during put.
Does a larger heap fix it? It shifts the problem to GC pause time and cache misses.
#capacity#memory#design
Q106
Sorting stability and equal priority: tasks with equal priority must run FIFO. What do you do?
advanced
Wrap tasks with an AtomicLong sequence number and compare by priority then sequence, since PriorityQueue is not stable.
record Item<T>(int prio, long seq, T task) {}var pq = new PriorityQueue<Item<Runnable>>( Comparator.comparingInt((Item<Runnable> i) -> i.prio()) .thenComparingLong(Item::seq));
⚠ Follow-up traps
Does PriorityBlockingQueue solve it? No, same lack of stability.
Overflow of the sequence? A long counter will not realistically overflow.