Alle Tabs der Lerneinheit (Statisches Array · Dynamische Liste · Vergleich · Interaktiv · Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Diese Lerneinheit wurde für typische Bachelor-Klausuren konzipiert. So prüfen wir · Fehler entdeckt? Melde ihn uns oder markiere die fragliche Stelle direkt im Text oben.
Alle Tabs der Lerneinheit (Statisches Array · Dynamische Liste · Vergleich · Interaktiv · Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Arrays und Listen speichern mehrere Werte geordnet hintereinander, mit Indexzugriff in O(1). Du lernst hier den Unterschied zwischen statischem Java-Array (int[], feste Größe), dynamischer Liste (ArrayList in Java, list in Python) und Pythons spezieller array.array-Variante; dazu typische Indexfehler (Off-by-one, ArrayIndexOutOfBoundsException), Komplexitäten wie O(1), O(n) und amortisiert O(1), und die wichtigsten Klausur-Stolperer rund um ArrayList<Integer>.remove und Einfügen am Anfang. Pflichtstoff im 1. Semester Informatik und Wirtschaftsinformatik.
Ein statisches Array ist eine geordnete Sammlung von Elementen mit fester Größe, die beim Anlegen festgelegt wird. Du kannst Werte lesen und überschreiben, aber keine Elemente hinzufügen oder löschen. In Java die klassische int[]-Notation, in Python eher selten (dort sind Listen meist dynamisch).
Was du in der Klausur können musst:
arr[i] in O(1), null-basiert (erstes Element ist arr[0])arr.length in Java, len(arr) in Pythonint[] arr = new int[5]; legt 5 Felder an, alle mit 0int[][] matrix für 2D, Zugriff via matrix[i][j]In Klausuren ist die häufigste Falle: ArrayIndexOutOfBoundsException beim Zugriff auf arr[arr.length]. Plus die Frage welche Komplexität hat ein Array-Durchlauf? (O(n) für eine for-Schleife über alle Elemente).
// Größe direkt beim Anlegen festlegen
int[] noten = new int[5]; // [0, 0, 0, 0, 0]
// Mit Werten initialisieren
int[] tage = {31, 28, 31, 30, 31};
// Zugriff per Index
int erste = tage[0]; // 31
tage[1] = 29; // Schaltjahr, set
int laenge = tage.length; // 5, feste LängeKlausur-Trick: arr.length (Java) ist kein Methodenaufruf, sondern eine Eigenschaft. Daher ohne Klammern. Bei Strings und ArrayList sind es dagegen Methoden mit Klammern: s.length(), list.size().
Eine dynamische Liste wächst und schrumpft automatisch. Du musst die Größe nicht vorher festlegen, das System reserviert intern Speicher und vergrößert/verkleinert ihn bei Bedarf.
In Java heißt sie ArrayList, in Python schlicht list. Beide sind dynamische Array-ähnliche Listen mit O(1)-Indexzugriff und amortisiert O(1)-Append. Java ArrayList<Integer> ist generisch/typisiert, Python list kann heterogene Elemente enthalten. Python list ist intern eine dynamische Array-Struktur (kein Linked List).
Die meiste Zeit nimmst du in der Praxis dynamische Listen. Sie sind flexibel und schnell genug für fast alles.
import java.util.ArrayList;
ArrayList<Integer> noten = new ArrayList<>();
noten.add(15); // [15]
noten.add(12); // [15, 12]
noten.add(0, 8); // [8, 15, 12], am Anfang einfügen
int erste = noten.get(0); // 8
noten.set(1, 16); // [8, 16, 12]
noten.remove(1); // [8, 12]
boolean hat = noten.contains(15); // false
int laenge = noten.size(); // 2// Klassische for-Schleife
for (int i = 0; i < noten.size(); i++) {
System.out.println(noten.get(i));
}
// For-Each (sauberer)
for (int note : noten) {
System.out.println(note);
}
// Mit Stream (modern)
noten.forEach(System.out::println);Faustregel zum Mitnehmen: Am Ende ist billig, am Anfang ist teuer. Wer eine Liste oft vorne ergänzen muss, sollte eine andere Datenstruktur wählen (typisch Deque/ArrayDeque). LinkedList verbessert zwar Einfügen vorne, verschlechtert aber den Indexzugriff von O(1) auf O(n) und hat schlechtere Cache-Lokalität, deshalb ist eine Deque meist die bessere Faustregel.
Beide Datenstrukturen speichern Werte mit Index-Zugriff. Der Unterschied liegt in der Größe: fest oder veränderbar.
Bei ArrayList<Integer> sind remove(int index) und remove(Object o) überladen. list.remove(1) ruft remove(int) (Index!) auf, nicht remove(Object) (Wert!). Klassischer Klausur-Stolperer.
add(x) hängt am Ende an: O(1) amortisiert. add(0, x) fügt am Anfang ein und muss alle anderen Elemente eine Position nach rechts schieben: O(n). Hier mit 4 Elementen sichtbar.
Anmelden, um den Fortschritt zu speichern.
Nächster Schritt
Aktives Abrufen festigt Wissen schneller als nochmal lesen.
Arrays und Listen speichern mehrere Werte geordnet hintereinander, mit Indexzugriff in O(1). Du lernst hier den Unterschied zwischen statischem Java-Array (int[], feste Größe), dynamischer Liste (ArrayList in Java, list in Python) und Pythons spezieller array.array-Variante; dazu typische Indexfehler (Off-by-one, ArrayIndexOutOfBoundsException), Komplexitäten wie O(1), O(n) und amortisiert O(1), und die wichtigsten Klausur-Stolperer rund um ArrayList<Integer>.remove und Einfügen am Anfang. Pflichtstoff im 1. Semester Informatik und Wirtschaftsinformatik.
Ein statisches Array ist eine geordnete Sammlung von Elementen mit fester Größe, die beim Anlegen festgelegt wird. Du kannst Werte lesen und überschreiben, aber keine Elemente hinzufügen oder löschen. In Java die klassische int[]-Notation, in Python eher selten (dort sind Listen meist dynamisch).
Was du in der Klausur können musst:
arr[i] in O(1), null-basiert (erstes Element ist arr[0])arr.length in Java, len(arr) in Pythonint[] arr = new int[5]; legt 5 Felder an, alle mit 0int[][] matrix für 2D, Zugriff via matrix[i][j]In Klausuren ist die häufigste Falle: ArrayIndexOutOfBoundsException beim Zugriff auf arr[arr.length]. Plus die Frage welche Komplexität hat ein Array-Durchlauf? (O(n) für eine for-Schleife über alle Elemente).
// Größe direkt beim Anlegen festlegen
int[] noten = new int[5]; // [0, 0, 0, 0, 0]
// Mit Werten initialisieren
int[] tage = {31, 28, 31, 30, 31};
// Zugriff per Index
int erste = tage[0]; // 31
tage[1] = 29; // Schaltjahr, set
int laenge = tage.length; // 5, feste LängeJava int[]: Größe in eckigen Klammern beim Anlegen. tage.length ist read-only, Größe ist fix.
# Python hat KEIN eingebautes statisches Array wie Java int[].
# array.array ist typisiert und speichereffizient,
# aber weiterhin eine MUTABLE Sequenz (kann wachsen/schrumpfen):
from array import array
zahlen = array('i', [1, 2, 3, 4, 5]) # 'i' = int
erste = zahlen[0] # 1
zahlen[1] = 99 # set
laenge = len(zahlen) # 5
zahlen.append(6) # geht, array.array ist NICHT statisch!
# Außerhalb der Grundlagen nutzt man für numerische Arrays oft
# Spezialbibliotheken wie NumPy. Hier konzentrieren wir uns auf
# list (dynamisch, siehe nächster Tab) und array.array.Python array.array ist typisiert und speichereffizient, aber dynamisch wie list, kein echtes statisches Array. Java int[] hat dagegen feste Länge.
| Operation | Java | Komplexität |
|---|---|---|
| get(i), Element an Position lesen | arr[i] | O(1) |
| set(i, x), Element an Position überschreiben | arr[i] = x | O(1) |
| length, Größe abfragen | arr.length | O(1) |
Beide Hauptoperationen sind O(1): die Elemente liegen intern so, dass die Laufzeitumgebung die Position eines Index direkt aus dem Startpunkt + i · Elementgröße berechnen kann, ohne durch die Liste zu laufen.
int[] nicht gehtInteraktive Visualisierung
Visualisiert statisches Array mit fester Größe, Index-Zugriff und Memory-Layout.
Klausur-Trick: arr.length (Java) ist kein Methodenaufruf, sondern eine Eigenschaft. Daher ohne Klammern. Bei Strings und ArrayList sind es dagegen Methoden mit Klammern: s.length(), list.size().
Eine dynamische Liste wächst und schrumpft automatisch. Du musst die Größe nicht vorher festlegen, das System reserviert intern Speicher und vergrößert/verkleinert ihn bei Bedarf.
In Java heißt sie ArrayList, in Python schlicht list. Beide sind dynamische Array-ähnliche Listen mit O(1)-Indexzugriff und amortisiert O(1)-Append. Java ArrayList<Integer> ist generisch/typisiert, Python list kann heterogene Elemente enthalten. Python list ist intern eine dynamische Array-Struktur (kein Linked List).
Die meiste Zeit nimmst du in der Praxis dynamische Listen. Sie sind flexibel und schnell genug für fast alles.
import java.util.ArrayList;
ArrayList<Integer> noten = new ArrayList<>();
noten.add(15); // [15]
noten.add(12); // [15, 12]
noten.add(0, 8); // [8, 15, 12], am Anfang einfügen
int erste = noten.get(0); // 8
noten.set(1, 16); // [8, 16, 12]
noten.remove(1); // [8, 12]
boolean hat = noten.contains(15); // false
int laenge = noten.size(); // 2Java ArrayList: typsicher mit Generics. Beachte: noten.get(i) statt noten[i]! Und size() mit Klammern, anders als length bei int[].
noten = []
noten.append(15) # [15]
noten.append(12) # [15, 12]
noten.insert(0, 8) # [8, 15, 12], am Anfang einfügen
erste = noten[0] # 8
noten[1] = 16 # [8, 16, 12]
noten.pop(1) # [8, 12]
hat = 15 in noten # False
laenge = len(noten) # 2Python list: keine Type-Annotations nötig. Index-Zugriff direkt mit []. Sehr kompakt.
Das ist klausurwichtig: welche Operation ist O(1), welche O(n)?
| Operation | Java ArrayList | Python list | Komplexität |
|---|---|---|---|
| Zugriff per Index | list.get(i) | list[i] | O(1) |
| Am Ende anhängen | list.add(x) | list.append(x) | amortisiert O(1) |
| Vom Ende entfernen | list.remove(list.size() - 1) | list.pop() |
// Klassische for-Schleife
for (int i = 0; i < noten.size(); i++) {
System.out.println(noten.get(i));
}
// For-Each (sauberer)
for (int note : noten) {
System.out.println(note);
}
// Mit Stream (modern)
noten.forEach(System.out::println);Drei gängige Wege. For-Each ist meist die sauberste Wahl, wenn du den Index nicht brauchst.
# Klassisch über Index
for i in range(len(noten)):
print(noten[i])
# Pythonisch: direkt iterieren
for note in noten:
print(note)
# Mit Index UND Wert
for i, note in enumerate(noten):
print(f"{i}: {note}")enumerate() ist das pythonische Pendant zur Java-for-i-Schleife wenn du beides brauchst.
Klick durch die Operationen und beobachte was passiert. Die Animation zeigt, welche Elemente bewegt werden bei jeder Operation.
Interaktive Visualisierung
Zeigt Array- und ArrayList-Operationen (push, pop, insert, remove) mit Index-Verschiebung.
Faustregel zum Mitnehmen: Am Ende ist billig, am Anfang ist teuer. Wer eine Liste oft vorne ergänzen muss, sollte eine andere Datenstruktur wählen (typisch Deque/ArrayDeque). LinkedList verbessert zwar Einfügen vorne, verschlechtert aber den Indexzugriff von O(1) auf O(n) und hat schlechtere Cache-Lokalität, deshalb ist eine Deque meist die bessere Faustregel.
Beide Datenstrukturen speichern Werte mit Index-Zugriff. Der Unterschied liegt in der Größe: fest oder veränderbar.
| Statisches Array | Dynamische Liste | |
|---|---|---|
| Größe | fest (beim Anlegen) | wächst und schrumpft |
| Java | int[] | ArrayList<Integer> |
| Python | kein direktes eingebautes statisches Array; array.array ist typisiert, aber dynamisch (für echte feste Arrays nimmt man üblicherweise NumPy ndarray) | list |
| Index-Zugriff | O(1) | O(1) |
| Set an Position | O(1) | O(1) |
| Am Ende anfügen | nicht möglich | O(1) amortisiert |
| Am Anfang einfügen | nicht möglich | O(n) |
| Speicher | minimal, fest reserviert | etwas Overhead, dynamisch |
| Länge abfragen | arr.length (Property) | list.size() / len(list) |
| Anwendungsfall | Wähle |
|---|---|
| Größe ist vorher bekannt und fest (12 Monate, 7 Wochentage) | Statisches Array |
| Maximale Performance, minimaler Speicher | Statisches Array |
| 2D-Matrizen mit fixer Größe | Statisches 2D-Array |
| Du weißt vorher nicht wie viele Elemente | Dynamische Liste |
| Du musst oft anhängen/entfernen | Dynamische Liste |
| Standardfall in der Praxis | Dynamische Liste |
In den meisten praktischen Fällen nimmst du eine dynamische Liste. Statische Arrays nutzt du, wenn Größe, Speicherlayout oder Performance bewusst festgelegt werden sollen, oder wenn die Größe wirklich fest ist.
ArrayList ist intern selbst ein statisches Array, nur dass es bei Bedarf neu angelegt und kopiert wird:
ArrayList hat intern eine Kapazität. Beispiel-Schema:
add(5): size=1, Kapazität noch frei
add(8): size=2, Kapazität noch frei
... (bis Kapazität voll)
add(99) bei voller Kapazität:
→ neues größeres Array anlegen
→ alle Werte kopieren (O(n))
→ 99 hinzufügen
Die konkrete Anfangskapazität und Wachstumsstrategie sind Implementierungsdetails der jeweiligen Java-Version. Seit Java 8 ist die initiale Kapazität einer leeren
ArrayList0 und wird typischerweise beim erstenaddauf 10 gesetzt. Die offizielle API garantiert vor allem das Verhalten (amortisiert konstantesadd), nicht eine exakte Verdopplung oder eine bestimmte Resize-Anzahl.
Daher ist add() amortisiert O(1): über viele Anhänge-Operationen verteilt sich die gelegentliche Kopierarbeit so, dass der Aufwand pro Aufruf gemittelt konstant bleibt; die genaue Anzahl und Strategie der Resizes ist Implementierungsdetail.
Frage: Du musst eine Liste von 1000 Elementen 500-mal am Anfang ergänzen. Was ist der Gesamt-Aufwand?
Grobe Klausur-Abschätzung: 500 × O(n) ≈ 500 × 1000 = 500.000 Verschiebungen.
Exakter (wenn die Liste dabei wächst): Summe von 1000 bis 1499 per Gauß-Formel ((1000 + 1499) · 500)/2 = 624.750 Verschiebungen.
Asymptotisch in jedem Fall O(k · n + k²), also linear pro Insert am Anfang. ArrayList ist dafür ungeeignet, eine LinkedList oder Deque wäre besser.
Drei interaktive Demos zu den häufigsten Klausur-Stolperern bei Arrays und Listen: ArrayIndexOutOfBoundsException beim Off-by-one, die ArrayList<Integer>.remove(int) vs remove(Integer) Überladungs-Falle, und add(0, x) vs add(x) mit Element-Verschiebung. Klicke auf Step oder Auto und beobachte, was Schritt für Schritt passiert.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Bei ArrayList<Integer> sind remove(int index) und remove(Object o) überladen. list.remove(1) ruft remove(int) (Index!) auf, nicht remove(Object) (Wert!). Klassischer Klausur-Stolperer.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
add(x) hängt am Ende an: O(1) amortisiert. add(0, x) fügt am Anfang ein und muss alle anderen Elemente eine Position nach rechts schieben: O(n). Hier mit 4 Elementen sichtbar.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Klausurfragen mit Lösungen (8)
Antwort: Du kannst mit add(x) Elemente anhängen
Erklärung: int[] hat keine add-Methode, die Größe ist fix. Wenn du dynamisch wachsen willst, brauchst du ArrayList. Die anderen Aussagen stimmen.
Antwort: O(1)
Erklärung: Index-Zugriff ist O(1): das Array kann direkt zur Speicheradresse springen. Egal ob i=0 oder i=999, gleicher Aufwand. Das gilt für statische UND dynamische Arrays.
Antwort: 1.000.000
Erklärung: Beim Einfügen an Position 0 müssen alle 1.000.000 bestehenden Elemente eine Position nach rechts. Das ist O(n).
ArrayList<Integer> a = new ArrayList<>();
a.add(10); a.add(20); a.add(30);
a.add(1, 99);
System.out.println(a.get(2));Antwort: 20
Erklärung: Nach den drei add/append: [10, 20, 30]. Nach insert(1, 99): [10, 99, 20, 30]. a[2] ist 20.
Antwort: list.contains(x) / x in list
Erklärung: `contains()` bzw. der `in`-Operator macht eine lineare Suche durch alle n Elemente, O(n). `size`/`len` ist O(1) (intern mitgezählt), `get(0)`/`list[0]` ist Index-Zugriff O(1), `add` ans Ende ist **amortisiert** O(1) (gelegentlicher Resize ist intern O(n), gemittelt aber konstant).
Antwort: Weil die Vergrößerung so selten passiert, dass amortisiert O(1) übrig bleibt
Erklärung: Wenn das Array voll ist, wird intern ein größeres Array angelegt und alle Elemente kopiert (O(n)). Über `n` Anhänge-Operationen entstehen nur **O(log n) Resize-Ereignisse** und insgesamt `O(n)` Kopierarbeit. Über alle Aufrufe gemittelt ergibt das **amortisiert O(1)**. Die genaue Wachstumsstrategie (Verdopplung oder anderer Faktor) ist Implementierungsdetail der Java-Version.
Antwort: Dynamische Liste (ArrayList / list)
Erklärung: Bei unbekannter Größe nimmst du eine dynamische Liste. Sie wächst automatisch. Statische Arrays nur wenn die Größe vorher feststeht.
Antwort: length ist eine Property (ohne Klammern), size() ist eine Methode (mit Klammern)
Erklärung: Klassischer Klausur-Trickfrage: arr.length ist eine Property (kein Klammern), list.size() ist eine Methode (mit Klammern). Verwechslung ist häufige Fehlerquelle in Klausuren.
Diese Einschränkungen gelten für Java
int[], feste Länge. Pythonarray.arrayist dagegen mutable und unterstütztappend,pop,insert. Es ist also kein echtes statisches Array, sondern eine typisierte dynamische Sequenz.
Wenn du diese Operationen brauchst, musst du in Java auf eine dynamische Liste (ArrayList) umsteigen. Mehr dazu im nächsten Tab.
Index-Zugriff und set in Aktion. Beide Operationen O(1), keine Größenänderung möglich.
| typischerweise O(1) |
| Am Anfang einfügen | list.add(0, x) | list.insert(0, x) | O(n) |
| Vom Anfang entfernen | list.remove(0) | list.pop(0) | O(n) |
| An Position einfügen | list.add(i, x) | list.insert(i, x) | O(n) |
| An Position entfernen | list.remove(i) | list.pop(i) | O(n) |
| Linear suchen | list.contains(x) | x in list | O(n) |
| Länge | list.size() | len(list) | O(1) |
Warum sind Operationen am Anfang teuer?
Wenn du an Position 0 einfügst, müssen alle anderen Elemente um eine Position nach rechts wandern. Bei einer Million bestehender Elemente sind das etwa eine Million Verschiebungen plus das Schreiben des neuen Elements, asymptotisch O(n).
Ans Ende anhängen ist meist O(1), außer das Array muss intern vergrößert werden, dann ist es O(n) für diesen Schritt. Das passiert aber so selten, dass man von amortisiert O(1) spricht.
Java ArrayList<Integer>-Falle:
remove(int index)undremove(Object o)sind überladen. BeiArrayList<Integer>wirdlist.remove(1)als Index-Löschung interpretiert (entfernt Index 1). Um den Wert 1 zu entfernen:list.remove(Integer.valueOf(1)).