liveBook · Manning

Immutable collection

As explained in 100 Java Mistakes and How to Avoid Them

An immutable collection is a collection whose state cannot be changed after construction.

An immutable collection cannot have its state changed after it is created. In Java practice, collections are often described as unmodifiable when operations such as adding, removing, or replacing elements are unsupported. Treating a collection as mutable when it is not causes an UnsupportedOperationException at runtime. section 8.14 section 8.5

Do not infer mutability from a declared List, Set, Map, or Collection type: Java’s type system does not encode it. A value may be mutable at one call site and unmodifiable at another, making code that calls add, remove, set, or sort conditionally fragile. section 8.5 section 8.0

Recognize that Java collection variants offer different mutation capabilities:

  • Arrays.asList() permits replacing existing list elements with set(), but not adding or removing them. section 8.5
  • A set returned by Map.keySet() permits removals but not additions. section 8.5
  • Collections.emptyList() and Collections.singletonList() are unmodifiable; sorting them is a no-op because zero or one element needs no rearrangement. section 8.5
  • List.of() may reject sort() even for empty or singleton lists, because it is unmodifiable. section 8.5

A result whose mutability changes with input

Returning Collections.emptyList() for empty input but a new ArrayList for nonempty input makes the same sanitize result mutable only sometimes. A later strings.add("Custom...") succeeds for nonempty input and fails for empty input, a branch that can evade tests. Keep returned mutability consistent instead of using a shared immutable empty result as an optimization when callers may modify it. section 8.5 section 8.5

When assembling data from several providers, build it in a mutable ArrayList and publish List.copyOf(data), or collect with Collectors.toUnmodifiableList(). This separates internal construction from the unmodifiable result exposed to callers. section 8.5 section 8.5

Unmodifiable collection factories also differ in null behavior. Replacing a legacy Collections.unmodifiableSet(...) with Set.of(...) can turn contains(null) from a false result into NullPointerException. Avoid a blind migration; guard a possibly null query with obj != null before calling contains. section 8.3 section 8.3

Static analysis can flag simple attempts to modify immutable collections, including IntelliJ IDEA’s Immutable Collection Is Modified warning. It cannot reliably settle every case, because determining how a collection was created may require complex interprocedural analysis. section 8.5

Figure 8.2 Standard Java collections categorized by mutability
figure

Compare standard Java collection families by mutability before choosing an API or assuming a returned collection can be changed. section 8.5

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains mutation restrictions, inconsistent API behavior, null-related migration risks, and limits of static analysis rather than collection internals.
Examples
Uses Arrays.asList, Map.keySet, List.of, a conditional sanitize result, List.copyOf, and Set.of null lookups.
What it assumes
Assumes familiarity with Java collection interfaces and mutation methods such as add, remove, set, and sort.
What you can do after
Diagnose/debug with it by identifying unsafe mutation calls and choosing consistently mutable or unmodifiable return values.
How it connects
Connects collection mutability with Java type system limits, List.of, Set.of, Map.keySet, null handling, and static analysis.

Also explained in

Compare how 24 books explain immutable collection →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.