Mit der Methode add() kann man einer Liste Objekte hinzufügen und dadurch wachsen lassen. Das Hinzufügen primitiver Datentypen wie int oder double zu einer Liste ist jedoch nicht auf direktem Wege möglich. Solche Datentypen müssen vor dem Hinzufügen mithilfe der Wrapper-Klassen in Objekte umgewandelt werden. Weitere Einzelheiten siehe Lexikon-Artikel "Wrapper-Klassen".
7.3.1 Zwei Varianten der add( )-Methode
Der folgende Quelltext enthält beide Varianten der add()-Methode.
import java.util.ArrayList;
public class Stringlist
{
ArrayList wortliste;
public Stringlist()
{
wortliste = new ArrayList<>();
addDemo();
}
public void addDemo()
{
wortliste.add("Hans"); // Variante 1
wortliste.add("Petra");
wortliste.add("Susanne");
wortliste.add("Maik");
wortliste.add("Tim");
wortliste.add(2,"Kay"); // Variante 2
}
}
Von der add()-Methode der Klasse ArrayList gibt es zwei Varianten.
Variante 1:
Die erste Variante des add()-Befehls fügt das Element an das Ende der vorhandenen Liste ein. Intern - aber das sieht der Benutzer nicht - wird das Element in den nächsten freien Platz des internen Arrays elementData eingefügt.
Variante 2:
Die zweite Variante des add()-Befehls fügt das Element in der angegebenen Position ein. Die folgenden Elemente rücken dann weiter nach rechts auf, dabei wird die Liste gegebenenfalls vergrößert (dynamisches Wachstum).
Primitive Datentypen in einer Liste und Auto-Boxing
import java.util.ArrayList;
public class WrapperDemo
{
public static void main(String[] args)
{
ArrayList zahlen = new ArrayList<>();
// Primitive int-Werte:
int a = 12;
int b = 25;
// Umwandlung in Integer-Objekte und Hinzufügen zur ArrayList
zahlen.add(Integer.valueOf(a));
zahlen.add(Integer.valueOf(b));
System.out.println(zahlen);
}
}
Die ArrayList zahlen speichert keine int-Werte, sondern Objekte der Klasse Integer. Deshalb werden die primitiven Werte a und b vor dem Hinzufügen mit Integer.valueOf(...) in passende Wrapper-Objekte umgewandelt.
Die neueren Java-Versionen ab 5 ermöglichen auch ein einfacheres Verfahren, das als Autoboxing bezeichnet wird:
zahlen.add(a); zahlen.add(b);
Beim Autoboxing (Einzelheiten siehe Seite im Bereich "Begriffe und Konzepte der OOP") übernimmt Java diese Umwandlung automatisch.
7.3.2 Aufbau von elementData
Der BlueJ-Objektinspektor zeigt uns, wie das Array elementData des ArrayList-Objekts wortliste genau aufgebaut ist:
Die ArrayList im BlueJ-Objektinspektor
"Hans" und "Petra" befinden sich an ihrer ursprünglichen Position, an Position 2 wurde "Kay" eingefügt, und die anderen drei Einträge sind nach hinten gerückt.
Interessant ist, dass das Array elementData eine Kapazität von zehn Elementen hat. Es ist in dem statischen Objekt-Array also noch Platz für vier weitere Elemente.
Wir fügen jetzt aber nicht vier, sondern fünf weitere Elemente zu wortliste hinzu. Dann untersuchen wir das Objekt wieder mit dem BlueJ-Objektinspektor.
Die um fünf Strings erweiterte Liste
Das Array elementData des ArrayList-Objekts wortliste hat jetzt eine Kapazität (length) von 15 Elementen, die Größe (size) ist aber 11.
Merke:
Kapazität und Größe einer ArrayList
Die Kapazität (length) beschreibt die Länge des internen Arrays, auf dem die Liste basiert. Sie gibt also an, wie viele Elemente maximal gespeichert werden könnten, ohne dass ein neues Array angelegt werden muss.
Die Größe (size) hingegen gibt stets die tatsächliche Anzahl der aktuell in der Liste gespeicherten Objekte an.
7.3.3 "Dynamisches" Wachstum eines ArrayList-Objekts
Wir wollen uns das "dynamische" Wachstum einer Arrayliste genauer ansehen und führen dazu ein kleines Experiment durch. Warum das Wort dynamisch in Anführungszeichen steht, werden wir am Ende dieses Abschnitts sehen.
Experiment
Bisher hatte das Array elementData eine Kapazität von 15 und eine Größe von 11. Wir fügen jetzt sechs weitere Elemente hinzu und betrachten elementData im BlueJ-Objektinspektor:
Die um sechs Strings erweiterte Liste
Das Array elementData umfasst jetzt 22 Elemente mit den Indizes 0 bis 21. Also ist das Array um 22 / 15 = 1,467 gewachsen, gerundet also 1,5.
In der aktuellen Java-Version wird die neue Kapazität der Liste nach der Formel
neue Kapazität = alte Kapazität + alte Kapazität / 2
berechnet. Diese Vergrößerungsregel ist aber ein internes Implementationsdetail und kann sich ändern. Für die Verwendung der ArrayList-Objekte ist nur wichtig, dass sie sich nach außen wie eine dynamisch wachsende Liste verhalten.
Wachstum einer Arrayliste
Autor: Ulrich Helmich 03/2026, Lizenz: Public domain
Dieses Bild zeigt das "dynamische" Wachstum einer ArrayList beim Hinzufügen neuer Einträge.
Nach Erzeugung von wortliste
Nach dem Erzeugen des ArrayList-Objekts wortliste ist die Größe (size) von wortliste gleich 0 und die Kapazität (length) des eigentlich verborgenen internen Arrays elementData ist ebenfalls 0. Mit dem BlueJ-Objektinspektor (oder anderen Tools) kann man dieses Array dennoch sehen und inspizieren. Aber eine Anweisung wie
String s = wortliste.elementData[1];
liefert eine Fehlermeldung des Compilers: elementData ist nicht öffentlich.
Nach Hinzufügen des ersten Objekts
Wenn der Liste das erste Objekt hinzugefügt wurde, erhält size den Wert 1, während elementData jetzt erst initialisiert wird und danach 10 Elemente umfasst.
Die Pfeile in den 10 Elementen von elementData sollen veranschaulichen, dass nicht die konkreten Objekte in elementData gespeichert sind, sondern Referenzen bzw. Verweise auf solche Objekte. Verweist ein Array-Element nicht auf ein Objekt, hat es den Wert null.
Nach Hinzufügen von fünf weiteren Objekten
Wenn wir noch weitere fünf Objekte zur Liste hinzufügen, werden die nächsten fünf "freien Plätze" der Liste aufgefüllt; sie enthalten jetzt Verweise auf die konkreten Objekte. Die restlichen vier Plätze der Liste enthalten weiterhin den Wert null.
Nach der erneuten Aufnahme von fünf Objekten
Die Liste hat noch Platz für genau vier weitere Elemente. Was passiert aber, wenn wir fünf neue Elemente hinzufügen wollen?
In diesem Fall setzt das "dynamische" Wachstum des internen Arrays elementData ein. Das Array der Länge3 10 wird um den Faktor 1,5 verlängert, also um fünf weitere Elemente. Daher hat length jetzt den Wert 15. Die fünf neuen Objekte können also problemlos aufgenommen werden. Danach hat size Wert 11, und es ist noch Platz für vier weitere Objekte in der Liste.
Simulation des "dynamischen" Wachstums mit einem statischen Array
Die folgende Java-Methode demonstriert, wie ein normales statisches int-Array zahlen um den Faktor 2 wachsen kann:
public void simuliereWachstum()
{
int[] kopie = new int[zahlen.length * 2];
for (int i=0; i < zahlen.length; i++)
kopie[i] = zahlen[i];
zahlen = kopie;
}
Es wird einfach lokal eine neue Array-Variable kopie angelegt, die doppelt so groß ist wie das ursprüngliche Array. Dann werden alle Elemente von zahlen in das neue Array hineinkopiert.
Der entscheidende Schritt erfolgt ganz zum Schluss: Die Referenz-Variable zahlen, die auf die konkreten Daten im Speicher verweist, wird mit zahlen = kopie auf das neu erzeugte und doppelt so große Array umgebogen.
Für den außenstehenden Betrachter ist die Referenz-Variable zahlen also immer noch vorhanden, nur verweist zahlen jetzt auf einen doppelt so großen Bereich im Speicher als vorher.
Warum "dynamisch" in Anführungszeichen steht
Von echtem dynamischem Wachstum spricht man dann, wenn eine Datenstruktur intern Element für Element wächst.
Bei einem ArrayList-Objekt ist das anders: Es arbeitet intern mit dem statischen Objekt-Array elementData.
Wird dieses Array zu klein, wird nicht ein Element angehängt, sondern es wird ein neues, größeres Array erzeugt und die bisherigen Elemente werden dorthin kopiert.
Ein ArrayList-Objekt wirkt nach außen also dynamisch, intern basiert es aber auf einem statischen Array.
Deshalb setzt man das Wort dynamisch bei der ArrayList gern in Anführungszeichen: "Dynamisches" Wachstum.
Ein Beispiel für richtiges dynamisches Wachstum
Das folgende Quelltext-Beispiel ist noch aus einem anderen Grund hoch interessant: Es zeigt, wie man eine innere Klasse definiert. Hier schon mal vorab ein Auszug aus diesem Quelltext:
public class Stack
{
public class Knoten
{
Object wert;
Knoten next;
public Knoten(Object w)
{
wert = w;
next = null;
}
}
private Knoten tos;
public Stack()
{
tos = null;
}
public boolean isEmpty()
{
return (tos == null);
}
// weitere Methoden
}
Alle Methoden der äußeren Klasse Stack können auf die innere Klasse Knoten zugreifen, auch auf die zwei Instanzvariablen wert und next, selbst wenn diese als private deklariert wären, was aber nicht der Fall ist.
Auch alle Klassen im gleichen Paket wie Stack können auf die öffentliche innere Klasse Knoten zugreifen, auch auf die beiden Instanzvariablen. Klassen außerhalb des Pakets können dagegen nicht auf die Instanzvariablen und den Konstruktor von Knoten zugreifen.
7.3.4 Echtes dynamisches Wachstum am Beispiel Stack
Das Thema "Dynamische Datenstrukturen" wird normalerweise in der Qualifikationsphase des Oberstufen-Unterrichts behandelt und ist in NRW auch Gegenstand der schriftlichen und mündlichen Abiturprüfungen.
Als Studierende der Informatik sollten Sie dieses Thema natürlich ebenfalls nicht nur kennen, sondern auch beherrschen.
Im Kurs "Algorithmen und Datenstrukturen" werden Sie die Datenstruktur Stack sicherlich ebenfalls behandeln, und wahrscheinlich auch auf einem wesentlich höherem Niveau.
Auf dieser Seite können Sie dies alles über den Abstrakten Datentyp Stack und seine dynamische Implementierung nachlesen, wenn Ihnen das Thema aus dem Schulunterricht nicht mehr geläufig ist oder wenn Sie das Thema nie im Unterricht hatten.
Seitenanfang -
Weiter mit wichtigen Methoden ...