Collections and Generics¶
The Java Collections Framework separates interfaces such as List, Set,
Queue, and Map from implementations with different performance and ordering
properties.
Program to the required contract¶
static List<String> normalizedNames(Collection<String> names) {
List<String> result = new ArrayList<>(names.size());
for (String name : names) {
result.add(name.strip().toLowerCase(Locale.ROOT));
}
return List.copyOf(result);
}
The parameter requires only iteration and size, while the return contract is an unmodifiable list. “Unmodifiable” does not make referenced mutable elements deeply immutable.
Generics¶
Generics provide compile-time type safety. Java generics are invariant:
List<Integer> is not a subtype of List<Number>. Wildcards express variance
at an API boundary.
static double sum(List<? extends Number> values) {
double total = 0;
for (Number value : values) total += value.doubleValue();
return total;
}
static void addDefaults(List<? super Integer> destination) {
destination.add(0);
destination.add(1);
}
The mnemonic PECS means producer-extends, consumer-super. A value read
from ? super Integer is only known to be an Object; a non-null arbitrary
Number cannot be safely added to ? extends Number.
Selection guide¶
| Need | Typical implementation |
|---|---|
| Indexed sequence | ArrayList |
| Unique values, no iteration order requirement | HashSet |
| Insertion-ordered set/map | LinkedHashSet / LinkedHashMap |
| Sorted keys | TreeSet / TreeMap |
| Stack or queue | ArrayDeque |
| Priority access | PriorityQueue |
Common mistakes¶
- modifying a collection during enhanced iteration outside the iterator contract;
- using mutable objects as hash keys;
- assuming
HashMapiteration order; - returning a mutable internal collection directly;
- selecting a concurrent collection without understanding its atomic operations.