Zum Inhalt springen
Java Anfänger 35 min

Collections (List, Set, Map)

Das Java Collections Framework: ArrayList, HashSet, HashMap und mehr. Dynamische Datenstrukturen für jeden Anwendungsfall.

Aktualisiert:

Collections (List, Set, Map)

Arrays haben eine feste Groesse — das ist unpraktisch. Collections sind dynamische Datenstrukturen, die wachsen und schrumpfen koennen. Das Java Collections Framework bietet fuer jeden Anwendungsfall die passende Struktur.

Ueberblick: Die drei Haupttypen

TypBeschreibungDuplikateReihenfolgeBeispiel
ListGeordnete SammlungJaJa (Index)Einkaufsliste
SetEinzigartige ElementeNeinNicht garantiertE-Mail-Adressen
MapSchluessel-Wert-PaareSchluessel: NeinAbhaengig von ImplementierungTelefonbuch

List — Geordnete Sammlung

ArrayList (am haeufigsten)

import java.util.ArrayList;
import java.util.List;

// Erstellen
var namen = new ArrayList<String>();
namen.add("Max");
namen.add("Anna");
namen.add("Leo");

// Oder kuerzer (unveraenderlich):
var namenFix = List.of("Max", "Anna", "Leo");

// Oder kuerzer (veraenderlich):
var namenFlex = new ArrayList<>(List.of("Max", "Anna", "Leo"));

Wichtige List-Methoden

var liste = new ArrayList<>(List.of("A", "B", "C", "D"));

// Zugriff
liste.get(0);           // "A"
liste.size();           // 4
liste.isEmpty();        // false
liste.contains("B");   // true
liste.indexOf("C");    // 2

// Hinzufuegen
liste.add("E");         // Am Ende: [A, B, C, D, E]
liste.add(1, "X");      // An Position 1: [A, X, B, C, D, E]

// Aendern
liste.set(0, "Z");      // Element ersetzen: [Z, X, B, C, D, E]

// Entfernen
liste.remove("X");      // Nach Wert: [Z, B, C, D, E]
liste.remove(0);        // Nach Index: [B, C, D, E]

// Durchlaufen
for (var element : liste) {
    System.out.println(element);
}

// Sortieren
liste.sort(String::compareTo);           // Alphabetisch
liste.sort(String.CASE_INSENSITIVE_ORDER); // Case-insensitive

List.of() vs. new ArrayList

// Unveraenderlich (immutable) -- zum Lesen
var fixListe = List.of("A", "B", "C");
// fixListe.add("D"); // FEHLER! UnsupportedOperationException

// Veraenderlich (mutable) -- zum Aendern
var flexListe = new ArrayList<>(List.of("A", "B", "C"));
flexListe.add("D"); // OK!

Vergleich mit Python

# Python: Listen
namen = ["Max", "Anna", "Leo"]
namen.append("Julia")
namen[0]  # "Max"
len(namen)  # 4
// Java: ArrayList
var namen = new ArrayList<>(List.of("Max", "Anna", "Leo"));
namen.add("Julia");
namen.get(0);   // "Max"
namen.size();   // 4

Set — Einzigartige Elemente

HashSet (am haeufigsten)

import java.util.HashSet;
import java.util.Set;

var fruechte = new HashSet<String>();
fruechte.add("Apfel");
fruechte.add("Banane");
fruechte.add("Apfel");  // Duplikat -- wird ignoriert!

System.out.println(fruechte);       // [Banane, Apfel] (keine Reihenfolge!)
System.out.println(fruechte.size()); // 2

// Oder unveraenderlich:
var fixSet = Set.of("Apfel", "Banane", "Kirsche");

Set-Operationen

var setA = new HashSet<>(Set.of(1, 2, 3, 4, 5));
var setB = new HashSet<>(Set.of(4, 5, 6, 7, 8));

// Vereinigung (Union)
var vereinigung = new HashSet<>(setA);
vereinigung.addAll(setB);
System.out.println(vereinigung); // [1, 2, 3, 4, 5, 6, 7, 8]

// Schnittmenge (Intersection)
var schnitt = new HashSet<>(setA);
schnitt.retainAll(setB);
System.out.println(schnitt); // [4, 5]

// Differenz
var differenz = new HashSet<>(setA);
differenz.removeAll(setB);
System.out.println(differenz); // [1, 2, 3]

Wann Set statt List?

// Duplikate aus einer Liste entfernen
var mitDuplikaten = List.of(1, 2, 3, 2, 1, 4, 3, 5);
var ohneDuplikate = new ArrayList<>(new HashSet<>(mitDuplikaten));
System.out.println(ohneDuplikate); // [1, 2, 3, 4, 5]

// Enthaltensein pruefen (Set ist VIEL schneller als List!)
var erlaubteNamen = Set.of("Admin", "Moderator", "User");
if (erlaubteNamen.contains("Admin")) {
    System.out.println("Zugang erlaubt!");
}

Map — Schluessel-Wert-Paare

HashMap (am haeufigsten)

import java.util.HashMap;
import java.util.Map;

var telefonbuch = new HashMap<String, String>();
telefonbuch.put("Max", "0171-1234567");
telefonbuch.put("Anna", "0172-2345678");
telefonbuch.put("Leo", "0173-3456789");

// Zugriff
System.out.println(telefonbuch.get("Max"));    // 0171-1234567
System.out.println(telefonbuch.get("Julia"));  // null (nicht vorhanden)

// Sicherer Zugriff
System.out.println(telefonbuch.getOrDefault("Julia", "Nicht gefunden"));

// Oder unveraenderlich:
var fixMap = Map.of("Max", "0171-1234567", "Anna", "0172-2345678");

Wichtige Map-Methoden

var noten = new HashMap<String, Double>();
noten.put("Mathe", 2.3);
noten.put("Deutsch", 1.7);
noten.put("Englisch", 1.0);

// Grundlegende Operationen
noten.size();                    // 3
noten.containsKey("Mathe");     // true
noten.containsValue(1.0);       // true
noten.remove("Deutsch");         // Entfernt Eintrag

// Alle Schluessel
noten.keySet();   // [Mathe, Englisch]

// Alle Werte
noten.values();   // [2.3, 1.0]

// Alle Eintraege
noten.entrySet(); // [Mathe=2.3, Englisch=1.0]

// Durchlaufen
for (var eintrag : noten.entrySet()) {
    System.out.printf("%s: %.1f%n", eintrag.getKey(), eintrag.getValue());
}

// Oder kompakter
noten.forEach((fach, note) ->
    System.out.printf("%s: %.1f%n", fach, note)
);

Haeufigkeitsanalyse mit Map

var text = "hallo welt hallo java welt hallo";
var woerter = text.split(" ");

var haeufigkeit = new HashMap<String, Integer>();
for (var wort : woerter) {
    haeufigkeit.merge(wort, 1, Integer::sum);
}

System.out.println(haeufigkeit);
// {hallo=3, java=1, welt=2}

Welche Collection wann?

SituationVerwendeGrund
Geordnete ListeArrayListIndex-Zugriff, Reihenfolge
Keine DuplikateHashSetEinzigartigkeit, schnelles contains()
Schluessel-WertHashMapSchneller Zugriff ueber Schluessel
Sortierte ListeArrayList + sort()Sortierung nach Bedarf
Sortiertes SetTreeSetAutomatisch sortiert
Sortierte MapTreeMapAutomatisch nach Schluessel sortiert
Thread-sicherConcurrentHashMapMehrere Threads
WarteschlangeLinkedList / ArrayDequeFIFO-Prinzip

Streams mit Collections

var studenten = List.of(
    new Student("Max", 2.3),
    new Student("Anna", 1.0),
    new Student("Leo", 3.7),
    new Student("Julia", 1.3),
    new Student("Tom", 4.0)
);

// Filtern
var bestanden = studenten.stream()
    .filter(s -> s.note() <= 4.0)
    .toList();

// Sortieren
var nachNote = studenten.stream()
    .sorted((a, b) -> Double.compare(a.note(), b.note()))
    .toList();

// Durchschnitt
var durchschnitt = studenten.stream()
    .mapToDouble(Student::note)
    .average()
    .orElse(0);

// Namen sammeln
var alleNamen = studenten.stream()
    .map(Student::name)
    .toList();

System.out.println("Bestanden: " + bestanden);
System.out.printf("Durchschnitt: %.1f%n", durchschnitt);

(Hier ist Student ein record Student(String name, double note) {})

Unveraenderliche Collections (Empfohlen)

// Unveraenderlich -- bevorzugen!
var namen = List.of("Max", "Anna", "Leo");
var zahlen = Set.of(1, 2, 3);
var daten = Map.of("key1", "val1", "key2", "val2");

// Kopie einer veraenderlichen Collection als unveraenderlich
var original = new ArrayList<>(List.of("A", "B", "C"));
var kopie = List.copyOf(original);

Uebungen

Uebung 1: Einkaufsliste

Erstelle eine Einkaufsliste mit ArrayList. Implementiere Methoden zum Hinzufuegen, Entfernen, Sortieren und Anzeigen.

Uebung 2: Wort-Zaehler

Lies einen Text ein und zaehle, wie oft jedes Wort vorkommt (mit HashMap). Sortiere die Ergebnisse nach Haeufigkeit.

Uebung 3: Kontaktbuch

Erstelle ein Kontaktbuch (Map<String, Kontakt>) mit Suche, Hinzufuegen und Loeschen.

Uebung 4: Lotterie

Generiere 6 einzigartige Zufallszahlen (1-49) mit einem HashSet und sortiere sie.

Was kommt als Naechstes?

In der naechsten Lektion lernst du Generics — damit kannst du eigene typsichere Collections und Klassen erstellen.

Zusammenfassung

  • List (ArrayList): Geordnet, Duplikate erlaubt, Index-Zugriff
  • Set (HashSet): Keine Duplikate, schnelles contains()
  • Map (HashMap): Schluessel-Wert-Paare, schneller Zugriff
  • List.of(), Set.of(), Map.of() erstellen unveraenderliche Collections
  • Streams ermoeglichen funktionale Operationen (filter, map, reduce)
  • Bevorzuge unveraenderliche Collections, wenn moeglich
  • ArrayList ist die meistverwendete Collection in Java

Pro-Tipp: Deklariere deine Variablen immer mit dem Interface-Typ statt dem konkreten Typ: List<String> namen = new ArrayList<>() statt ArrayList<String> namen = new ArrayList<>(). So kannst du die Implementierung spaeter austauschen, ohne den Rest des Codes aendern zu muessen. Das ist ein wichtiges Designprinzip: “Programmiere gegen Schnittstellen, nicht gegen Implementierungen.”

Zurück zum Java Kurs