Listen
Kurz gesagt: Eine Liste ist eine Collection, die von selbst wächst und schrumpft; ArrayList hält die Elemente der Reihe nach wie ein Array, und List<String> sagt, welchen Typ sie haben.
Problem
Der Warenkorb ist voll
Du schreibst den Warenkorb eines Onlineshops und hältst die Artikel in einem Array. Aber ein Array hat eine Größe, die sich nicht ändert. Legt der Kunde einen vierten Artikel hinein, legst du ein größeres Array an und kopierst alles. Nimmt er einen Artikel heraus, bleibt eine Lücke:
String[] cart = { "Brot", "Milch", "Kaffee" };
// Ein vierter Artikel: Das Array ist voll, also legen wir ein größeres an und kopieren.String[] bigger = new String[cart.length + 1];for (int i = 0; i < cart.length; i++) { bigger[i] = cart[i];}bigger[cart.length] = "Butter";cart = bigger;
// Der Kunde nimmt die Milch heraus.cart[1] = null;
for (String item : cart) { System.out.println(item);}BrotnullKaffeeButternull überspringen. Und die Zahl der Artikel ist nicht mehr cart.length.Das ist viel Code für etwas, das jeder Shop ständig macht.
Die Idee
ArrayList: ein Array, das sich selbst kümmert
Java hat dafür eine fertige Klasse: ArrayList. Sie hält die Elemente in einem Array, erledigt das Kopieren und Verschieben aber selbst. So eine Collection heißt Liste:
import java.util.ArrayList;
public class Main { public static void main(String[] args) { ArrayList<String> cart = new ArrayList<>(); cart.add("Brot"); cart.add("Milch"); cart.add("Kaffee"); cart.add("Butter"); cart.remove("Milch"); System.out.println(cart); System.out.println("Artikel: " + cart.size()); }}[Brot, Kaffee, Butter]Artikel: 3ArrayListliegt im Paketjava.util, darum beginnt die Datei mit einemimport, wie beiScanner.addhängt hinten an, undremoveentfernt und schließt die Lücke: „Kaffee“ rückt auf den Platz von „Milch“.size()ist die Zahl der Elemente gerade jetzt. Es ist nichtlength, weil eine Liste kein Array ist.printlngibt die ganze Liste in eckigen Klammern aus.
So sieht es in ArrayList aus. Die Zahl in den Klammern ist die Anfangsgröße des Arrays. Ohne sie ist es 10. Hier ist es 3, damit du siehst, was passiert, wenn das Array voll wird:
ArrayList<String> cart = new ArrayList<>(3);cart.add("Brot");cart.add("Milch");cart.add("Kaffee");cart.add("Butter");cart.remove("Milch");System.out.println(cart);System.out.println("Artikel: " + cart.size());Schritt für Schritt, in Worten
- cart zeigt auf ein ArrayList-Objekt. Darin liegen ein Array mit 3 Plätzen und ein Zähler size.
- add legt jedes Element auf den ersten freien Platz und erhöht size.
- Das Array ist voll. ArrayList legt ein neues mit 4 Plätzen an und kopiert die drei Elemente hinein.
- Das Objekt zeigt jetzt auf das neue Array, das alte braucht niemand mehr. „Butter“ kommt auf den freien Platz.
- remove entfernt „Milch“, und alles danach rückt einen Platz nach links. Es bleibt keine Lücke.
- Von außen siehst du nur eine Liste mit drei Artikeln: Das Kopieren und Verschieben erledigt ArrayList.
Die Idee
Was in die spitzen Klammern gehört
ArrayList<String> bedeutet „eine Liste mit Text“. Der Typ in den spitzen Klammern heißt Typparameter (Generics). Er sagt dem Compiler, was in der Liste ist, und der Compiler setzt es durch:
import java.util.ArrayList;
public class Main { public static void main(String[] args) { ArrayList<String> cart = new ArrayList<>(); cart.add("Brot"); cart.add(5); }}Main.java:7: error: incompatible types: int cannot be converted to String cart.add(5); ^Darum gibt cart.get(0) direkt einen String zurück, ohne Umwandlung.
Rechts sind die spitzen Klammern leer: new ArrayList<>(). Der Compiler nimmt den Typ von der linken Seite.
Meist wird die Variable mit dem Interface List deklariert, und die Klasse ArrayList steht nur nach new:
List<String> cart = new ArrayList<>();cart.add("Brot");System.out.println(cart.get(0));Das ist die Polymorphie aus dem Modul „Vererbung und Polymorphie“: List sagt, was eine Liste kann, und ArrayList ist eine Art, es zu tun. Du brauchst zwei imports: java.util.ArrayList und java.util.List. Ab hier zeigt die Lektion sie nicht mehr.
Die Idee
Indizes: get, set, add, indexOf
Eine Liste hat Indizes wie ein Array, von 0 bis size() - 1. Aber statt [ ] nimmst du Methoden:
List<String> tasks = new ArrayList<>();tasks.add("Rechnung März");tasks.add("Bank anrufen");tasks.add("Lagerbericht");
System.out.println(tasks.get(0));tasks.set(1, "Termin bei der Bank");tasks.add(0, "Kaffee mit dem Team");System.out.println(tasks);System.out.println(tasks.indexOf("Lagerbericht"));System.out.println(tasks.contains("Bank anrufen"));Rechnung März[Kaffee mit dem Team, Rechnung März, Termin bei der Bank, Lagerbericht]3falseget(i)liest, undset(i, x)ersetzt.add(i, x)fügt bei Indexiein und schiebt den Rest nach rechts.indexOf(x)sucht und gibt den Index oder-1zurück, undcontains(x)sagt nur, ob es darin ist.
Genauer, für Neugierige
- Ein Index außerhalb der Liste bricht das Programm ab, wie bei einem Array:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3containsundindexOfvergleichen mitequals, nicht mit==. Darum finden sie gleichen Text, nicht nur dasselbe Objekt.- Einfügen und Entfernen vorne sind in einer großen Liste langsam: Jedes Element nach dem Index rückt einen Platz weiter. Bei einer Million Elementen sind das eine Million Verschiebungen.
Probier es aus
Wer ist dran?
Die Liste der Patienten, die beim Arzt warten. Jonas geht hinein, und Anna hat einen Termin, darum bekommt sie den zweiten Platz.
Was gibt das Programm aus?
List<String> waiting = new ArrayList<>();waiting.add("Jonas");waiting.add("Maria");waiting.add("Peter");waiting.remove(0);waiting.add(1, "Anna");System.out.println(waiting + " " + waiting.size());remove(0) entfernt Jonas, und Maria wird Erste, bei Index 0. add(1, "Anna") fügt Anna bei Index 1 ein und schiebt Peter nach rechts. Drei bleiben übrig.
Die Idee
Die Elemente durchlaufen
Eine Liste durchläufst du wie ein Array: mit for-each, wenn du nur die Elemente brauchst, oder mit einem Index, wenn du auch die Nummer brauchst:
List<String> cart = new ArrayList<>();cart.add("Brot");cart.add("Kaffee");cart.add("Butter");
for (String item : cart) { System.out.println("- " + item);}for (int i = 0; i < cart.size(); i++) { System.out.println((i + 1) + ". " + cart.get(i));}- Brot- Kaffee- Butter1. Brot2. Kaffee3. ButterGenauer, für Neugierige
- Entferne keine Elemente aus einer Liste, während du sie mit for-each durchläufst. Das Programm bricht ab:
for (String item : cart) { if (item.equals("Brot")) { cart.remove(item); }}Exception in thread "main" java.util.ConcurrentModificationExceptionDie Exception kommt nicht immer. Entfernst du das vorletzte Element, endet die Schleife zu früh, und das letzte wird nie geprüft. Verlass dich also nicht darauf.
- Wenn du entfernen musst, durchläufst du mit einem Index von hinten nach vorne. So verschiebt das Entfernen nicht die Elemente, die du noch nicht geprüft hast:
List<String> cart = new ArrayList<>();cart.add("Brot");cart.add("Milch");cart.add("Brot");for (int i = cart.size() - 1; i >= 0; i--) { if (cart.get(i).equals("Brot")) { cart.remove(i); }}System.out.println(cart);[Milch]removeIf.Die Idee
Zahlen in einer Liste: Integer
Eine Liste mit Noten sieht so aus, lässt sich aber nicht kompilieren:
ArrayList<int> scores = new ArrayList<>();Main.java:5: error: unexpected type ArrayList<int> scores = new ArrayList<>(); ^ required: reference found: intIn die spitzen Klammern gehört eine Klasse, und int ist keine Klasse. Darum hat jeder primitive Typ eine Hüllklasse: Integer für int, Double für double, Boolean für boolean, Character für char.
List<Integer> scores = new ArrayList<>();scores.add(85);scores.add(64);scores.add(91);
int total = 0;for (int score : scores) { total += score;}System.out.println("Durchschnitt: " + (double) total / scores.size());Durchschnitt: 80.0scores.add(85) bekommt ein int, aber die Liste will ein Integer. Java packt es von selbst in eine Hülle. Das heißt Autoboxing. In der Schleife ist int score das Gegenteil: Unboxing. Fast immer merkst du den Unterschied nicht.
Genauer, für Neugierige
- Vergleiche
Integer-Werte mitequals, nicht mit==.==prüft, ob die beiden Variablen auf dasselbe Objekt zeigen:
Integer a = 127, b = 127;Integer c = 128, d = 128;System.out.println(a == b);System.out.println(c == d);System.out.println(c.equals(d));truefalsetrueJava hält fertige Objekte für die Zahlen von -128 bis 127 bereit, darum zeigen bei 127 beide Pfeile auf ein Objekt. Bei 128 sind es zwei Objekte.
- Ein
Integerkannnullsein, einintnicht. Packst dunullaus, bricht das Programm mitNullPointerExceptionab. Das begegnet dir in der Lektion überHashMap.
Probier es aus
Finde den Fehler
Ein Theater hält die belegten Plätze in einer Liste. Ein Kunde gibt Platz 2 zurück, und das Programm soll [12, 7, 5] ausgeben. Stattdessen gibt es [12, 2, 5] aus. In welcher Zeile steckt der Fehler?
Wähle die Zeile mit dem Fehler.
List hat zwei Methoden remove: remove(int index) und remove(Object o). In remove(2) ist das Argument ein int, also wird die erste aufgerufen, und sie entfernt das Element bei Index 2, also Platz 7. Um den Wert 2 zu entfernen, übergib ein Objekt: seats.remove(Integer.valueOf(2)). Eine List<String> hat diese Falle nicht, weil Text nie ein Index ist.Die Idee
Sortieren und eine fertige Liste
Collections.sort sortiert die Liste an Ort und Stelle: Text alphabetisch, Zahlen nach Größe. Die Klasse Collections liegt auch in java.util.
List<String> cities = new ArrayList<>();cities.add("Hamburg");cities.add("Berlin");cities.add("Dresden");Collections.sort(cities);System.out.println(cities);
List<Integer> prices = new ArrayList<>(List.of(30, 5, 12));Collections.sort(prices);System.out.println(prices);[Berlin, Dresden, Hamburg][5, 12, 30]List.of(30, 5, 12) erzeugt eine fertige Liste aus den Werten, die du aufzählst. Aber sie ist unveränderlich: Du kannst darin nichts hinzufügen, entfernen oder sortieren.
List<String> days = List.of("Mo", "Di", "Mi");days.add("Do");Exception in thread "main" java.lang.UnsupportedOperationExceptionDarum werden die Preise oben in eine neue ArrayList kopiert: new ArrayList<>(List.of(30, 5, 12)) ist eine Liste, die du ändern kannst.
Genauer, für Neugierige
- Text wird nach den Codes seiner Zeichen sortiert. Großbuchstaben kommen vor Kleinbuchstaben, darum kommt „Traube“ vor „apfel“:
List<String> fruit = new ArrayList<>(List.of("apfel", "Birne", "banane", "Traube"));Collections.sort(fruit);System.out.println(fruit);[Birne, Traube, apfel, banane]- Wie du eigene Objekte sortierst, zum Beispiel Produkte nach Preis, siehst du in der Lektion „Klassen in Klassen“.
Übung
Listen in Klassen
private-Feld der Klasse, und main ruft nur ihre Methoden auf.1. Ein Bücherregal. Eine Klasse BookShelf mit einer Methode addBook(String title), die das Buch ans Ende stellt, und takeBook(), die das erste Buch zurückgibt und entfernt (oder null, wenn das Regal leer ist). Füge count() und toString() hinzu. Füge in main „Unter dem Joch“, „Tabak“ und „Der eiserne Leuchter“ hinzu, nimm ein Buch und gib den Rest aus.
Genommen: Unter dem Joch2 übrig: [Tabak, Der eiserne Leuchter]2. Ein Ereignisprotokoll. Eine Klasse Event mit einem Datum und einer Beschreibung und eine Klasse EventLog mit den Methoden addEvent(String date, String description) und getEventsBetween(String from, String to), die eine Liste der Ereignisse zwischen den beiden Daten zurückgibt, einschließlich. Die Daten sind Text in der Form 2026-03-31. In dieser Form sortiert sich der Text genauso wie die Daten, darum vergleicht compareTo aus der Lektion über Text sie richtig. Füge vier Ereignisse hinzu: 2026-01-15 „Jahresinventur“, 2026-03-31 „Bericht erstes Quartal“, 2026-05-20 „Neuer Kaffeelieferant“, 2026-09-01 „Neues Schuljahr“. Gib die vom 2026-03-01 bis 2026-06-30 aus.
2026-03-31 Bericht erstes Quartal2026-05-20 Neuer Kaffeelieferant3. Ein Notizbuch. Eine Klasse Note mit einem Titel und einem Inhalt und eine Klasse Notebook mit den Methoden addNote, findNote(String title) (gibt die Notiz oder null zurück), deleteNote(String title) (gibt true zurück, wenn es etwas gelöscht hat) und count(). Füge die Notizen „OOP“, „Collections“ und „SQL“ hinzu, finde „Collections“, lösche „OOP“ und prüfe, dass sie weg ist.
Collections: ArrayList wächst von selbstGelöscht: OOPNotizen: 2Es gibt keine Notiz OOP.4. Kopfrechnen. Eine Klasse Question mit einem Text und der richtigen Antwort und eine Klasse MathGame mit einer Liste von Fragen, einer Methode addQuestion und einer Methode start(Scanner in). start stellt die Fragen nacheinander, liest die Antwort und sagt am Ende, wie viele richtig waren. Die Fragen sind 2 + 2, 3 * 4 und 15 - 9.
41272 + 2 = Richtig!3 * 4 = Richtig!15 - 9 = Falsch, die Antwort ist 6.Ergebnis: 2 von 3Weitere Aufgaben
- Keine Wiederholungen. Lies 6 Namen ein und sammle sie in einer Liste, wobei du die überspringst, die schon darin sind. Für die Eingabe Jonas, Maria, Jonas, Anna, Maria, Peter ist die Ausgabe
[Jonas, Maria, Anna, Peter]. - Der teuerste Artikel. Eine List<Double> enthält Preise. Finde den höchsten und seinen Index, ohne
Collections. - Die Liste umdrehen. Schreib eine Methode, die eine neue Liste mit denselben Elementen in umgekehrter Reihenfolge zurückgibt. Ändere das Original nicht.
- Eine Einkaufsliste. Lies die Befehle
add milk,remove milk,listundendund halte die Liste zwischen ihnen. Der Befehl, einen Artikel zu entfernen, der nicht darin ist, sagt „Kein solcher Artikel.“
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Polymorphie · Interfaces · Exceptions · Strings
- Geht weiter in: Stack, Queue und verkettete Liste · HashMap und HashSet · Hashcodes und Hashfunktionen · Klassen in Klassen
- Aufgaben zum Thema: Collections