Wer mit Java anfängt, stößt sehr schnell auf den Begriff Collection. Gemeint ist damit nicht einfach irgendeine Liste, sondern ein ganzes Framework – also eine Sammlung von Schnittstellen und Klassen, die es uns ermöglichen, Daten komfortabel zu speichern, zu durchsuchen und zu verarbeiten. Für viele Einsteiger ist das am Anfang ein undurchsichtiger Dschungel: ArrayList, HashSet, HashMap, LinkedList – was ist was, und wann verwende ich welches?
In diesem Beitrag möchte ich dir Schritt für Schritt zeigen, wie du die wichtigsten Typen der Java Collections verstehst und wie du sie praktisch einsetzen kannst. Wir konzentrieren uns dabei auf die vier Grundtypen: List, Set, Map und Queue. Ziel ist, dass du am Ende intuitiv weißt, wann du welche Datenstruktur verwendest und warum.
Das java.util-Paket enthält viele nützliche Klassen, mit denen du Daten dynamisch speichern kannst – also im Gegensatz zu Arrays, deren Größe fix ist. Das Collection-Framework bietet einheitliche Methoden wie add(), remove(), contains() oder size(), unabhängig davon, ob du eine List, ein Set oder eine Queue nutzt. Das macht es sehr mächtig, weil du die konkrete Implementierung austauschen kannst, ohne deinen restlichen Code stark ändern zu müssen.
Schauen wir uns die einzelnen Strukturen jetzt etwas genauer an.
Eine List speichert Elemente in einer bestimmten Reihenfolge. Du kannst über den Index auf jedes Element zugreifen, genau wie bei einem Array. Das bekannteste Beispiel ist die ArrayList.
import java.util.*;
public class ListBeispiel {
public static void main(String[] args) {
List<String> namen = new ArrayList<>();
namen.add("Anna");
namen.add("Bernd");
namen.add("Clara");
namen.add("Anna"); // doppelt erlaubt
System.out.println("Liste: " + namen);
System.out.println("Erstes Element: " + namen.get(0));
namen.remove("Bernd");
System.out.println("Nach dem Entfernen: " + namen);
}
}
Ausgabe:
Liste: [Anna, Bernd, Clara, Anna] Erstes Element: Anna Nach dem Entfernen: [Anna, Clara, Anna]
Du siehst: In einer List sind doppelte Werte erlaubt. Die Reihenfolge bleibt so, wie du die Elemente hinzufügst. Wenn du also eine Sammlung brauchst, bei der du die Positionen der Elemente kennst und du auch Duplikate speichern willst, ist List die richtige Wahl.
Ein Set ist eine Sammlung, in der jedes Element nur einmal vorkommen darf. Wenn du versuchst, ein Element doppelt hinzuzufügen, wird es einfach ignoriert. Das bekannteste Beispiel ist das HashSet.
import java.util.*;
public class SetBeispiel {
public static void main(String[] args) {
Set<String> staedte = new HashSet<>();
staedte.add("Berlin");
staedte.add("Hamburg");
staedte.add("Muenchen");
staedte.add("Berlin"); // wird ignoriert
System.out.println("Staedte: " + staedte);
System.out.println("Enthaelt Hamburg? " + staedte.contains("Hamburg"));
}
}
Ausgabe (Reihenfolge kann variieren):
Staedte: [Berlin, Hamburg, Muenchen] Enthaelt Hamburg? true
Ein HashSet speichert Elemente nicht in einer bestimmten Reihenfolge. Wenn dir die Reihenfolge wichtig ist, kannst du ein LinkedHashSet verwenden – das merkt sich die Einfügereihenfolge. Wenn du die Elemente sortiert brauchst, nimm ein TreeSet.
Ein Set eignet sich hervorragend, wenn du eine Liste ohne Duplikate möchtest, zum Beispiel um eindeutige Nutzernamen oder IDs zu speichern.
Eine Map ist keine direkte Unterklasse von Collection, aber sie gehört trotzdem zum Framework. Sie speichert Werte zu einem bestimmten Schlüssel. Du kannst dir das wie ein Wörterbuch vorstellen: Jeder Schlüssel (Key) steht für einen Wert (Value). Der wichtigste Vertreter ist HashMap.
import java.util.*;
public class MapBeispiel {
public static void main(String[] args) {
Map<String, Integer> alter = new HashMap<>();
alter.put("Anna", 25);
alter.put("Bernd", 30);
alter.put("Clara", 22);
System.out.println("Alter von Bernd: " + alter.get("Bernd"));
alter.put("Bernd", 31); // ueberschreibt alten Wert
System.out.println("Aktualisiert: " + alter);
alter.remove("Clara");
System.out.println("Nach Entfernen: " + alter);
}
}
Ausgabe:
Alter von Bernd: 30
Aktualisiert: {Anna=25, Bernd=31, Clara=22}
Nach Entfernen: {Anna=25, Bernd=31}
Eine Map ist ideal, wenn du Daten eindeutig zuordnen möchtest. Zum Beispiel kannst du Benutzernamen mit ihren IDs, Produkten mit Preisen oder Ländern mit ihren Hauptstädten verknüpfen.
Es gibt verschiedene Map-Implementierungen:
HashMap: keine bestimmte Reihenfolge.
LinkedHashMap: behält Einfügereihenfolge.
TreeMap: sortiert nach Schlüsseln.
Eine Queue (Warteschlange) speichert Elemente nach dem Prinzip „First In, First Out“ (FIFO). Das bedeutet: Das zuerst eingefügte Element wird auch als erstes wieder entfernt. Ein bekanntes Beispiel ist die LinkedList, die auch das Queue-Interface implementiert.
import java.util.*;
public class QueueBeispiel {
public static void main(String[] args) {
Queue<String> warteschlange = new LinkedList<>();
warteschlange.add("Kunde1");
warteschlange.add("Kunde2");
warteschlange.add("Kunde3");
System.out.println("Warteschlange: " + warteschlange);
String bedient = warteschlange.poll(); // entfernt erstes Element
System.out.println("Bedient: " + bedient);
System.out.println("Aktuelle Warteschlange: " + warteschlange);
}
}
Ausgabe:
Warteschlange: [Kunde1, Kunde2, Kunde3] Bedient: Kunde1 Aktuelle Warteschlange: [Kunde2, Kunde3]
Wenn du also eine Situation modellieren möchtest, in der Elemente in einer Reihenfolge „abgearbeitet“ werden (zum Beispiel Druckaufträge, Nachrichten oder Tasks), ist Queue genau richtig.
Um das Ganze nochmal übersichtlich einzuordnen:
List: erlaubt Duplikate, hat Reihenfolge, Zugriff per Index Set: keine Duplikate, Reihenfolge optional Map: Key-Value-Paare, Key eindeutig Queue: FIFO-Prinzip (First In, First Out)
Diese Unterschiede sind entscheidend, um die richtige Datenstruktur zu wählen. Wenn du dir nicht sicher bist, denke immer daran, was du brauchst: Reihenfolge? Eindeutigkeit? Schlüssel-Wert-Beziehungen?
Zum Abschluss ein Beispiel, das alle vier Strukturen kombiniert und zeigt, wie sie zusammenspielen könnten:
import java.util.*;
public class CollectionDemo {
public static void main(String[] args) {
List<String> bestellungen = Arrays.asList("Apfel", "Banane", "Apfel", "Birne");
Set<String> eindeutigeProdukte = new HashSet<>(bestellungen);
Map<String, Integer> lagerbestand = new HashMap<>();
Queue<String> verarbeitung = new LinkedList<>();
lagerbestand.put("Apfel", 10);
lagerbestand.put("Banane", 5);
lagerbestand.put("Birne", 3);
for (String produkt : eindeutigeProdukte) {
verarbeitung.add(produkt);
}
while (!verarbeitung.isEmpty()) {
String produkt = verarbeitung.poll();
int bestand = lagerbestand.get(produkt);
System.out.println("Bearbeite " + produkt + " (Bestand: " + bestand + ")");
}
}
}
Ausgabe:
Bearbeite Apfel (Bestand: 10) Bearbeite Banane (Bestand: 5) Bearbeite Birne (Bestand: 3)
Dieses Beispiel zeigt wunderbar, wie die verschiedenen Strukturen zusammenarbeiten: Die List erlaubt doppelte Bestellungen, das Set filtert sie heraus, die Map speichert Lagerbestände und die Queue verarbeitet die Produkte nacheinander.
Die Java Collections sind das Rückgrat vieler Programme. Sie ermöglichen es dir, Daten flexibel zu verwalten, egal ob du einfache Listen führst, eindeutige Mengen speicherst oder komplexe Zuordnungen benötigst. Wenn du ihre Eigenschaften verstehst, schreibst du nicht nur korrekteren, sondern auch effizienteren Code.
Mein Tipp: Experimentiere mit den verschiedenen Typen, ändere Datentypen, prüfe, wie sie sich verhalten, und lies im Debugger mit. So bekommst du schnell ein Gefühl dafür, wann List, Set, Map oder Queue die richtige Wahl ist. Schon bald wirst du merken, dass sie dein tägliches Werkzeug werden – ganz selbstverständlich und mächtig zugleich.
