Kapitel 8
Listen und Maps
Ein Array hat eine feste Größe. Oft weißt du aber vorher nicht, wie viele Elemente es werden: Einträge im Warenkorb, Songs in einer Playlist. Java bringt dafür fertige Sammlungen mit, die Collections. Die drei wichtigsten sind Liste, Set und Map. Alle liegen in java.util und brauchen einen import.
ArrayList
Eine ArrayList ist wie ein Array, das mitwächst. In spitzen Klammern steht, was hineinkommt:
List<String> names = new ArrayList<>();
Links steht der allgemeine Typ List, rechts die konkrete ArrayList. Die leeren Klammern <> (der „Diamant“) übernehmen den Typ von links.
add(x)hängt hinten an,get(i)liest Positioni(ab 0),set(i, x)ersetztsize()ist die Anzahl,isEmpty()prüft auf leerremove(i)entfernt Positioni, alles dahinter rutscht nach vorncontains(x)sucht ein Element
In spitze Klammern gehören nur Klassen. Für Zahlen schreibst du Integer statt int und Double statt double. Beim Hinzufügen und Lesen wandelt Java automatisch um. Eine Liste kannst du direkt ausgeben, anders als ein Array. List.of("a", "b") erzeugt schnell eine feste Liste, die sich danach nicht mehr ändern lässt.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Ada");
names.add("Bob");
names.add("Cleo");
System.out.println(names);
System.out.println("Size: " + names.size());
System.out.println("Index 1: " + names.get(1));
names.remove(0);
names.add("Dan");
System.out.println(names);
System.out.println(names.contains("Ada"));
List<Integer> squares = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
squares.add(i * i);
}
int sum = 0;
for (int n : squares) {
sum += n;
}
System.out.println(squares + " sum " + sum);
}
}Set: jedes Element nur einmal
Ein Set enthält jedes Element höchstens einmal. add gibt false zurück, wenn das Element schon drin ist, und lässt das Set unverändert. Damit entfernst du Doppelte oder zählst verschiedene Werte.
HashSet: schnell, aber ohne feste ReihenfolgeLinkedHashSet: behält die Reihenfolge, in der die Elemente dazukamen
Ein Set hat kein get(i). Brauchst du wieder eine Liste, übergibst du das Set dem Konstruktor: new ArrayList<>(set).
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> signUps = List.of("Mia", "Leo", "Mia", "Ana", "Leo");
Set<String> guests = new LinkedHashSet<>();
for (String name : signUps) {
boolean added = guests.add(name);
if (!added) {
System.out.println(name + " is already on the list");
}
}
System.out.println(guests);
System.out.println(guests.size() + " guests");
System.out.println(guests.contains("Ana"));
List<String> list = new ArrayList<>(guests);
System.out.println("Last: " + list.get(list.size() - 1));
}
}HashMap: Schlüssel und Wert
Eine Map speichert Paare aus Schlüssel und Wert, etwa Name → Telefonnummer. Map<String, String> nennt beide Typen.
put(key, value)speichert; gibt es den Schlüssel schon, wird der alte Wert ersetztget(key)liefert den Wert, odernull, wenn der Schlüssel fehltgetOrDefault(key, fallback)liefert stattdessen den ErsatzwertcontainsKey(key),size(),keySet()für alle Schlüssel
Zum Zählen nimmst du die bisherige Anzahl (oder 0) und speicherst sie plus eins, wie im Beispiel. Werte dürfen selbst Listen sein: Map<String, List<Integer>> speichert zu jedem Namen eine Liste von Noten.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> phone = new HashMap<>();
phone.put("Ada", "0151 123");
phone.put("Bob", "0160 456");
phone.put("Ada", "0170 789");
System.out.println(phone.get("Ada"));
System.out.println(phone.get("Eve"));
System.out.println(phone.getOrDefault("Eve", "unknown"));
System.out.println(phone.containsKey("Bob"));
System.out.println(phone.size() + " entries");
String text = "the cat and the hat and the bat";
Map<String, Integer> counts = new HashMap<>();
for (String word : text.split(" ")) {
counts.put(word, counts.getOrDefault(word, 0) + 1);
}
System.out.println("the: " + counts.get("the"));
System.out.println("and: " + counts.get("and"));
System.out.println("cat: " + counts.get("cat"));
}
}Typische Fehler
List<int>
List<int>meldet der Compiler mitunexpected type. In spitzen Klammern stehen nur Klassen:List<Integer>,Map<String, Double>.remove bei List<Integer>
removegibt es zweimal: mit einemintentfernt es eine Position, mit einem Objekt das Element. Bei einer Liste von Zahlen ist das eine Falle:List<Integer> numbers = new ArrayList<>(List.of(10, 20, 30)); numbers.remove(1); // removes position 1: [10, 30] numbers.remove(Integer.valueOf(10)); // removes the value 10: [30]Liste in for-each ändern
Entfernst oder ergänzt du Elemente, während eine for-each-Schleife über dieselbe Liste läuft, bricht das Programm mit
ConcurrentModificationExceptionab. Nimm eine normalefor-Schleife mit Index oder sammle in einer neuen Liste.Fehlender Schlüssel ergibt null
int n = counts.get("dog");bricht mitNullPointerExceptionab, wenn es den Schlüssel nicht gibt, weilnullkeine Zahl ist.getOrDefault(key, 0)oder vorhercontainsKeyprüfen.Reihenfolge bei HashMap und HashSet
HashMapundHashSetmerken sich nicht, in welcher Reihenfolge du etwas eingefügt hast. Verlass dich bei der Ausgabe nicht darauf. Brauchst du die Reihenfolge, nimmLinkedHashSetbzw.LinkedHashMap.