ReviseAlgo Logo

Common Java Pitfalls

Collection Mistakes

Understand the ConcurrentModificationException, custom key mutation issues, and different list initialization APIs.

Interview: Commonly tested. Expect questions on how ArrayList raises modification exceptions, hash collisions, and the difference between Arrays.asList() vs List.of().

Last Updated: June 13, 2026 9 min read

Java Collections are the workhorse of applications, but subtle API behaviors and performance traits are common sources of errors.

CoMod Exception

Thrown when structural modifications occur on collections while iterating through them with standard loops.

Mutable Keys

If a HashMap key object changes its internal state, its hashCode changes, making the entry unretrievable.

List Initializers

Arrays.asList() vs List.of() have key differences regarding null safety and structural mutability.

ConcurrentModificationException

When you create an Iterator (underlying a for-each loop), it copies the collection's structural modification count (modCount). If you modify the collection (add/remove) directly inside the loop, the iterator detects a mismatch in modCount and throws a ConcurrentModificationException.

Code Walkthrough

This program highlights array list initialization APIs and iteration modification bugs.

import java.util.*;

public class CollectionPitfallsDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

// Pitfall: Throws ConcurrentModificationException try { for (String item : list) { if ("B".equals(item)) { list.remove(item); // Modifies list structurally during iteration } } } catch (ConcurrentModificationException e) { System.out.println("Exception thrown: Cannot modify list during iteration!"); }

// Fix: Use Iterator explicitly Iterator<String> it = list.iterator(); while (it.hasNext()) { if ("B".equals(it.next())) { it.remove(); // Safe modification } }

// Initialization traps String[] arr = {"X", "Y"}; List<String> backedList = Arrays.asList(arr); // backedList.add("Z"); // UnsupportedOperationException! Backed by array size arr[0] = "W"; System.out.println(backedList.get(0)); // Prints "W"! Writes pass-through to array

List<String> immutableList = List.of("X", "Y"); // immutableList.set(0, "W"); // UnsupportedOperationException! Fully immutable } }

Interview-Relevant Information

Q: Compare Arrays.asList() vs List.of() in detail.
Answer:

  • Arrays.asList(arr) returns a list wrapper backed by the original array. Changes to the array reflect in the list and vice versa. It is fixed-size (cannot add or remove) but allows replacing elements (mutating values). Allows null values.
  • List.of(...) returns a fully unmodifiable list implementation (copying elements). No additions, removals, or replacements are allowed. It rejects null elements immediately (throws NPE).

Q: What happens if a custom object used as a Map key has mutable fields?
Answer: If the key object fields change, the calculated hashCode() changes. The bucket lookup calculation fails during subsequent reads. The item is effectively lost inside the Map, leaking memory and producing data inaccuracies. Map keys should always be immutable (like String, Integer, or records).

Quick Checklist

Do you know why List.of() throws on nulls? Can you modify a collection safely during iteration? If yes, you are ready to write clean collection management blocks.

Use Cases

Choosing appropriate list builders based on desired nullability and mutability traits.

Safely pruning items from lists during validation sweeps.

Common Mistakes

Using double-brace initialization (new ArrayList() {{ add('a'); }}) which implicitly creates anonymous inner subclasses, leaking outer-class references.

Using List.contains() on a massive LinkedList (scales O(N)) when a Set (scales O(1)) is appropriate.