Java 9 Collection Factory Methods: Unveränderliche List, Set & Map kompakt erzeugen
Das Problem vor Java 9
Unveränderliche Collections erforderten viel Boilerplate:
List<String> list = new ArrayList<>();
list.add("A"); list.add("B"); list.add("C");
list = Collections.unmodifiableList(list);
Java 9 Lösung: Statische Factory-Methoden
Die Interfaces List, Set, Map erhalten of() & ofEntries() Methoden, die unveränderliche Instanzen zurückgeben.
Signaturen (Auszug)
// List & Set: 0–10 Elemente + Varargs
static <E> List<E> of(E e1, E e2, E e3);
static <E> List<E> of(E... elements);
// Map: 0–10 Key-Value-Paare
static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
// Map: beliebig viele Einträge via Map.Entry
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K, ? extends V>... entries)
Wichtige Eigenschaften
- Unveränderlich: Jeder Mutationsversuch (
add,put,remove,clear) wirftUnsupportedOperationException. - Null-hostil:
nullElemente/Keys/Values →NullPointerExceptionbei Erstellung. - Keine Duplikate (Set/Map Keys): Doppelte Keys/Elemente →
IllegalArgumentException. - Serialisierbar: Implementieren
Serializable(wenn Elemente serialisierbar). - Keine bestimmte Implementierung: JVM-intern optimierte, speichereffiziente Implementierungen.
Beispiele
List & Set
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
List<String> empty = List.of();
Set<String> many = Set.of("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"); // Varargs
Map
Map<String, String> map = Map.of(
"A", "Apfel",
"B", "Birne",
"C", "Clementine"
);
Map<String, String> map2 = Map.ofEntries(
Map.entry("A", "Apfel"),
Map.entry("B", "Birne"),
Map.entry("C", "Clementine")
);
Vergleich: Alt vs. Neu
| Aspekt | Java 8 (Collections.unmodifiableXxx) | Java 9 (List.of / Map.of) |
|---|---|---|
| Syntax | Verbos, mehrzeilig | Kompakt, einzeilig, deklarativ |
| Null-Elemente | Erlaubt (in der modifizierbaren Phase) | Verboten (fail-fast bei Erstellung) |
| Performance | Wrapper um mutable Collection | Spezialisierte, kompakte Impl. |
| Serialisierung | Delegiert an wrapped Collection | Eigene, stabile Serialisierung |
Code-Beispiel: Vollständig
import java.util.*;
public class FactoryDemo {
public static void main(String[] args) {
Set<String> set = Set.of("A", "B", "C");
List<String> list = List.of("A", "B", "C");
Map<String, String> map = Map.of("A","Apfel","B","Birne","C","Clementine");
Map<String, String> mapEntries = Map.ofEntries(
Map.entry("A","Apfel"),
Map.entry("B","Birne"),
Map.entry("C","Clementine")
);
System.out.println(set); // [A, B, C]
System.out.println(list); // [A, B, C]
System.out.println(map); // {A=Apfel, B=Birne, C=Clementine}
System.out.println(mapEntries); // {A=Apfel, B=Birne, C=Clementine}
// Mutationsversuch → Exception
try { list.add("D"); } catch (UnsupportedOperationException e) {
System.out.println("Unveränderlich: " + e.getClass().getSimpleName());
}
}
}
Fazit
Die Factory-Methoden sind der empfohlene Weg für kleine, unveränderliche Collections in Java 9+. Sie sind lesbarer, performanter und sicherer (Null-Check bei Erstellung).
Java
- Java Operatoren meistern: Typen, Syntax und praktische Beispiele
- Java abstrakte Klassen und Methoden: Ein umfassender Leitfaden
- Java-Schnittstellen meistern: Konzepte, Implementierung und Best Practices
- Java Try-With-Resources meistern: Automatisches Ressourcenmanagement erklärt
- Java Annotations erklärt: Typen, Platzierung und praktische Beispiele
- Java Autoboxing und Unboxing meistern: Praktische Beispiele und Best Practices
- Java String toLowerCase() & toUpperCase(): Text-Groß-/Kleinschreibung mit Locale-Bewusstsein konvertieren
- Java Collections meistern: Umfassender Leitfaden für effiziente Datenstrukturen
- Java 10: 70+ neue APIs – Unmodifiable Collections, Optional.orElseThrow() & mehr
- Java 10: Garbage-Collector Interface (JEP 304) & Parallel Full GC für G1 (JEP 307)