A collection represents a group of elements through Java’s collection abstractions. Although the API is ubiquitous, operations that look uniform—searching, comparing, or modifying—can vary by collection implementation and fail silently or at run time. section 8.0 section 8.14
Treat these collection behaviors as implementation-dependent unless their contract is known:
- A lookup with an unrelated element type can return “not found” rather than throw; broad declarations such as List<Object> remove compiler protection. section 8.14
- Null handling differs: some collections store null, some reject null only on insertion, and others reject null during contains(). Guard a possibly null query before searching. section 8.3
- Mutability is not encoded in a collection’s declared type. Arrays.asList(), Map.keySet(), empty collections, and List.of() support different subsets of mutation operations. section 8.5
- Content equality is specified for List and Set, but requires care for queues, streams, wrappers from unmodifiableCollection(), and comparisons between a List and Set. section 7.2
static final List<String> allLanguages =
List.of("Java", "Groovy", "Scala", "Kotlin");
static boolean isLanguage(String language) {
return contains(language, allLanguages);
}
Passing a List to a generic varargs method can compile by inferring Object and wrapping the entire collection as one array element. A membership check then searches for the List itself and can always return false. section 2.9.2
An occasionally immutable result
A sanitizing method may return a mutable ArrayList for ordinary input but Collections.emptyList() for empty input. Code that later calls add() therefore succeeds in one path and throws UnsupportedOperationException in another. Keep a method’s mutability contract consistent, or return an explicit unmodifiable copy when callers must not modify the result. section 8.5
Prevent collection mistakes with focused checks:
- When changing an array variable into a collection, inspect every use, including calls that still compile; test both successful and unsuccessful boolean results. section 2.9.2
- Do not replace legacy unmodifiable collections with Java 9 factory collections without checking callers that may search for null. section 8.3
- Avoid depending on unspecified iteration order, mutating a collection during iteration or collection-lambda execution, and changing keys after inserting them into sets or maps. section 8.14
- Use static analysis as a prompt, not proof: IntelliJ IDEA can flag Iterable Is Used as Vararg, while mutability analysis may require complex interprocedural reasoning. section 2.9.2 section 8.5















