EMZETT.
Login

Collections

Kurz: Javas Standard-Framework (java.util) für Datenstrukturen mit variabler Größe — die zentralen Interfaces sind List, Set und Map.

Genauer: Anders als Arrays haben Collections keine feste Größe und bieten fertige Methoden für Sortieren, Suchen und Filtern. Seit Java 5 sind Collections generisch (siehe Generics) — List<String> erzwingt zur Compile-Zeit, dass nur String-Objekte hineinkommen, statt Typfehler erst zur Laufzeit zu entdecken.

Im Detail

Das Collections-Framework ist als Hierarchie von Interfaces aufgebaut, die jeweils mehrere konkrete Implementierungen mit unterschiedlichen Performance-Eigenschaften haben:

List<String> geordnet = new ArrayList<>();  // erlaubt Duplikate, Reihenfolge bleibt erhalten
Set<String> eindeutig = new HashSet<>();    // keine Duplikate, KEINE garantierte Reihenfolge
Map<String, Integer> zuordnung = new HashMap<>(); // Schlüssel-Wert-Paare
 
geordnet.add("Ben"); geordnet.add("Ben"); // beide landen drin
eindeutig.add("Ben"); eindeutig.add("Ben"); // nur einmal enthalten
 
zuordnung.put("Ben", 25);
zuordnung.get("Ben"); // 25

Die utility-Klasse Collections (Singular vs. Plural ist eine häufige Verwechslung: java.util.Collection ist das Basis-Interface, java.util.Collections die Klasse mit statischen Hilfsmethoden wie sort(), max(), unmodifiableList()) bietet fertige Algorithmen, die auf jeder Collection funktionieren, ohne dass man sie selbst implementieren muss. Collections.unmodifiableList(liste) liefert z. B. eine schreibgeschützte “Sicht” auf eine bestehende Liste — nützlich, um eine interne Datenstruktur nach außen zu geben, ohne dass der Aufrufer sie versehentlich verändern kann.

Die Interface-Hierarchie im Überblick

Das Wurzel-Interface Collection<E> wird von drei Hauptzweigen erweitert: List (geordnet, Duplikate erlaubt, Index-Zugriff), Set (keine Duplikate, meist keine garantierte Reihenfolge) und Queue/Deque (FIFO/LIFO-Verhalten für Warteschlangen und Stacks). Map<K, V> gehört technisch NICHT zu Collection (es hat Schlüssel-Wert-Paare statt einzelner Elemente), zählt aber trotzdem zum Collections-Framework dazu:

Deque<String> stapel = new ArrayDeque<>();
stapel.push("erstes");
stapel.push("zweites");
System.out.println(stapel.pop()); // "zweites" - Last In, First Out (Stack-Verhalten)
 
Queue<String> warteschlange = new LinkedList<>();
warteschlange.offer("erstes");
warteschlange.offer("zweites");
System.out.println(warteschlange.poll()); // "erstes" - First In, First Out

Typische Implementierungswahl

Jedes Interface hat mehrere konkrete Implementierungen mit unterschiedlichen Stärken: ArrayList (schneller Index-Zugriff) vs. LinkedList (schnelles Einfügen an den Enden) für List; HashSet (schnellster Zugriff, keine Reihenfolge) vs. TreeSet (sortiert, etwas langsamer) vs. LinkedHashSet (Einfügereihenfolge bleibt erhalten) für Set. Die Wahl hängt fast immer davon ab, welche Operation am häufigsten vorkommt — häufiges Lesen per Index spricht für ArrayList, häufiges Prüfen “ist X schon enthalten?” spricht für HashSet.

Streams als moderne Ergänzung

Seit Java 8 lassen sich Collections elegant mit der Stream-API verarbeiten, statt mit klassischen Schleifen:

List<String> namen = List.of("Anna", "Ben", "Clara");
List<String> grossbuchstaben = namen.stream()
    .filter(n -> n.length() > 3)
    .map(String::toUpperCase)
    .toList();

Thread-Sicherheit

Die Standard-Implementierungen (ArrayList, HashMap, HashSet) sind NICHT thread-sicher — mehrere Threads, die gleichzeitig schreibend zugreifen, können die interne Struktur beschädigen oder eine ConcurrentModificationException auslösen. Für nebenläufigen Zugriff gibt es entweder Collections.synchronizedList(liste) (wickelt jede Methode in synchronized ein, einfach aber langsam bei viel Konkurrenz) oder die spezialisierten Klassen aus java.util.concurrent wie ConcurrentHashMap, die intern feingranularer sperren und dadurch deutlich besser skalieren.

Siehe auch: List, Set, Generics, Iterator