EMZETT.
Login

Kurz: Das Collections Framework (java.util) bietet fertige, wachsende Datenstrukturen. Sie speichern Objekte und sind generisch: List<String> ist eine Liste von Strings.

Teil des Kurses Java

Kapitel 10 von 22 im Kurs Java. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Das Collections Framework (java.util) bietet fertige, wachsende Datenstrukturen. Sie speichern Objekte und sind generisch: List<String> ist eine Liste von Strings.

InterfaceIdeeTypische Klasse
List<E>geordnet, Duplikate erlaubt, Zugriff per IndexArrayList, LinkedList
Set<E>keine DuplikateHashSet, LinkedHashSet, TreeSet
Map<K, V>Schlüssel → WertHashMap, LinkedHashMap, TreeMap
Queue<E>, Deque<E>Warteschlange, StapelArrayDeque, PriorityQueue

List

import java.util.*;
 
public class Listen {
    public static void main(String[] args) {
        List<String> namen = new ArrayList<>();
        namen.add("Mia");
        namen.add("Tom");
        namen.add(1, "Zoe");                 // an Index einfügen
        System.out.println(namen + " " + namen.size());
        System.out.println(namen.get(0) + " " + namen.indexOf("Tom") + " " + namen.contains("Max"));
        namen.remove("Zoe");
        namen.set(0, "Mia2");
        System.out.println(namen);
 
        for (String n : namen) System.out.print(n + ";");
        System.out.println();
 
        List<Integer> zahlen = new ArrayList<>(List.of(5, 3, 9, 1));
        Collections.sort(zahlen);
        System.out.println(zahlen + " max " + Collections.max(zahlen) + " " + Collections.frequency(zahlen, 3));
        zahlen.removeIf(z -> z > 4);
        zahlen.replaceAll(z -> z * 10);
        System.out.println(zahlen);
    }
}

Ausgabe:

[Mia, Zoe, Tom] 3
Mia 2 false
[Mia2, Tom]
Mia2;Tom;
[1, 3, 5, 9] max 9 1
[10, 30]

List.of(...) erzeugt eine unveränderliche Liste. Änderungen werfen eine UnsupportedOperationException. Für eine veränderliche Kopie: new ArrayList<>(List.of(...)).

Achtung

Bei List<Integer> ist remove(1) der Index 1, remove(Integer.valueOf(1)) der Wert 1.

Set

import java.util.*;
 
public class Mengen {
    public static void main(String[] args) {
        Set<String> s = new HashSet<>(List.of("a", "b", "a", "c"));
        System.out.println(s.size() + " " + s.contains("b"));
 
        Set<Integer> sortiert = new TreeSet<>(List.of(5, 1, 3, 1));
        System.out.println(sortiert);                  // automatisch sortiert, ohne Duplikate
 
        Set<Integer> a = new TreeSet<>(List.of(1, 2, 3, 4)), b = new TreeSet<>(List.of(3, 4, 5));
        Set<Integer> schnitt = new TreeSet<>(a); schnitt.retainAll(b);
        Set<Integer> vereinigung = new TreeSet<>(a); vereinigung.addAll(b);
        Set<Integer> differenz = new TreeSet<>(a); differenz.removeAll(b);
        System.out.println(schnitt + " " + vereinigung + " " + differenz);
 
        List<String> mitDuplikaten = List.of("x", "y", "x", "z", "y");
        System.out.println(new LinkedHashSet<>(mitDuplikaten));   // Duplikate entfernen, Reihenfolge behalten
    }
}

Ausgabe:

3 true
[1, 3, 5]
[3, 4] [1, 2, 3, 4, 5] [1, 2]
[x, y, z]

Map

import java.util.*;
 
public class Karten {
    public static void main(String[] args) {
        Map<String, Integer> alter = new HashMap<>();
        alter.put("Mia", 17);
        alter.put("Tom", 19);
        alter.put("Mia", 18);                     // überschreibt
        System.out.println(alter.get("Mia") + " " + alter.get("Zoe") + " " + alter.getOrDefault("Zoe", -1));
        System.out.println(alter.containsKey("Tom") + " " + alter.size());
        alter.putIfAbsent("Zoe", 21);
        alter.merge("Tom", 1, Integer::sum);       // Wert verändern: 19 + 1
        alter.remove("Mia");
 
        Map<String, Integer> sortiert = new TreeMap<>(alter);
        for (Map.Entry<String, Integer> e : sortiert.entrySet()) {
            System.out.println(e.getKey() + " -> " + e.getValue());
        }
        System.out.println(sortiert.keySet() + " " + sortiert.values());
    }
}

Ausgabe:

18 null -1
true 2
Tom -> 20
Zoe -> 21
[Tom, Zoe] [20, 21]

Häufigkeiten zählen

import java.util.*;
 
public class Zaehlen {
    public static void main(String[] args) {
        String text = "das ist ein test das ist gut";
        Map<String, Integer> zaehler = new TreeMap<>();
        for (String wort : text.split(" ")) {
            zaehler.merge(wort, 1, Integer::sum);
        }
        System.out.println(zaehler);
 
        Map<Character, List<String>> nachBuchstabe = new TreeMap<>();
        for (String w : List.of("Apfel", "Ananas", "Birne", "Banane", "Kirsche")) {
            nachBuchstabe.computeIfAbsent(w.charAt(0), k -> new ArrayList<>()).add(w);
        }
        System.out.println(nachBuchstabe);
    }
}

Ausgabe:

{das=2, ein=1, gut=1, ist=2, test=1}
{A=[Apfel, Ananas], B=[Birne, Banane], K=[Kirsche]}

Queue und Deque

import java.util.*;
 
public class Schlangen {
    public static void main(String[] args) {
        Deque<Integer> stapel = new ArrayDeque<>();     // Stapel: zuletzt rein, zuerst raus
        stapel.push(1); stapel.push(2); stapel.push(3);
        System.out.println(stapel.pop() + " " + stapel.peek() + " " + stapel);
 
        Queue<String> schlange = new ArrayDeque<>();    // Schlange: zuerst rein, zuerst raus
        schlange.offer("A"); schlange.offer("B"); schlange.offer("C");
        System.out.println(schlange.poll() + " " + schlange.peek() + " " + schlange);
 
        PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(5, 1, 4, 2));   // kleinstes zuerst
        StringBuilder sb = new StringBuilder();
        while (!pq.isEmpty()) sb.append(pq.poll()).append(' ');
        System.out.println(sb.toString().trim());
    }
}

Ausgabe:

3 2 [2, 1]
A B [B, C]
1 2 4 5

Welche Collection nehme ich?

AufgabeWahl
geordnete, wachsende ListeArrayList
Duplikate entfernen / “ist enthalten?” schnellHashSet
sortiert haltenTreeSet, TreeMap
Reihenfolge des Einfügens merkenLinkedHashSet, LinkedHashMap
Schlüssel → WertHashMap
Stapel / SchlangeArrayDeque
nach PrioritätPriorityQueue

LinkedList ist selten die beste Wahl: ArrayList und ArrayDeque sind fast immer schneller.

Sortieren mit Comparator

import java.util.*;
 
public class Sortieren {
    record Person(String name, int alter) {}
 
    public static void main(String[] args) {
        List<Person> l = new ArrayList<>(List.of(new Person("Tom", 19), new Person("Mia", 17), new Person("Zoe", 19)));
        l.sort(Comparator.comparingInt(Person::alter).reversed().thenComparing(Person::name));
        System.out.println(l);
    }
}

Ausgabe:

[Person[name=Tom, alter=19], Person[name=Zoe, alter=19], Person[name=Mia, alter=17]]

Unveränderliche Collections und Kopien

List.of, Set.of, Map.of (und Map.entry) liefern unveränderliche Sammlungen. List.copyOf(x) erzeugt eine unveränderliche Kopie. Gib aus Klassen lieber unveränderliche Sichten zurück, damit niemand deinen Zustand von außen ändert.

Merke

  • Collections sind generisch: List<String>, Map<String, Integer>
  • ArrayList, HashSet, HashMap sind die Standardwahl; Tree... sortiert, LinkedHash... merkt die Reihenfolge
  • List.of, Set.of, Map.of sind unveränderlich
  • merge, computeIfAbsent, getOrDefault machen Maps bequem
  • ArrayDeque für Stapel und Schlangen
  • Sortieren mit Comparator.comparing(...)

Übungsaufgabe

Lies eine Liste von Wörtern ein und gib die drei häufigsten mit ihrer Anzahl aus (Map + sortieren).

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Arrays

Weiter: Klassen und Objekte

Alle Kapitel: Java im Überblick