Generics and Collections
Domain 4 tests type erasure, wildcard variance, and collection contracts: which implementation to choose, what happens with duplicate keys, and when iteration throws ConcurrentModificationException.
Generics
- Generics exist only at compile time; erasure removes type arguments, so
List<String>andList<Integer>share one runtime class. You cannot use primitives, testinstanceof List<String>, callnew T(), or create a generic array. - Bounds:
<T extends Number & Comparable<T>>- at most one class, listed first, then interfaces. - Wildcards follow PECS:
List<? extends Number>is a producer (you may readNumber, but adding is illegal);List<? super Integer>is a consumer (you may addInteger, but reading yields onlyObject). - Generic methods declare their own parameter before the return type:
static <T> T pick(List<T> list).
Collections
Listis ordered with duplicates;Setrejects duplicates byequals/hashCode;Mapkeys are unique.ArrayListis the general-purpose list;HashSet/HashMapare unordered with O(1) average access;TreeSet/TreeMapsort byComparableor aComparatorin O(log n).List.of,Set.of,Map.ofreturn immutable collections that rejectnulland throwUnsupportedOperationExceptionon mutation.HashMapallows one null key;HashtableandConcurrentHashMapdo not.- Mutating a collection while iterating with anything other than
Iterator.remove()triggersConcurrentModificationExceptionfrom fail-fast iterators.
Worked example
List<? extends Number> in = List.of(1, 2.0);
Number n = in.get(0); // fine
in.add(3); // compile error: unknown subtype of Number
List<? super Integer> out = new ArrayList<Number>();
out.add(3); // fine
Integer i = out.get(0); // compile error: only Object is guaranteed
Traps
Comparatormust return negative, zero or positive; an inconsistent comparator corrupts aTreeSet.- A mutable key whose
hashCodechanges becomes unreachable in aHashMap. Arrays.asListreturns a fixed-size list backed by the original array.