16.1.4 | Benutzerdefinierte Datenstrukturen |
Auch wenn es in Java keine Pointer im Sinne von C gibt, kann man dennoch dynamische Datenstrukturen erzeugen. Hierzu werden Objekte über Verweise verkettet.
Dies wird am Beispiel einer einfach verketteten Liste gezeigt. Um die einzelnen Listenelemente zu verwalten, benutzt man in C Strukturen und in Pascal Records. Solche Datenstrukturen existieren in Java nicht. Hier muss man die Datensätze mit den auf ihnen ausführbaren Operationen in Klassen zusammenfassen, um die gleiche Funktionalität zu erhalten.
Ein
herkömmliches Listenelement enthält immer einen Zeiger auf das nächste Element und
einen Datentyp. Für beide Bestandteile wird ein Verweis verwendet:
public class ListElement {
protected ListElement next = null;// Nächstes Element
protected Object obj = null; // Verwaltetes Objekt
public ListElement() {
}
public void setNext(ListElement next) {
this.next = next;
}
public ListElement getNext() {
return next;
}
public void setObject(Object obj) {
this.obj = obj;
}
public Object getObject() {
return obj;
}
}
Dieser Aufbau hat gegenüber C oder Pascal den Vorteil, dass man
nicht explizit einen Zeiger als Typ anlegen muss, da ohnehin
schon sämtliche Objekte als Verweise verwaltet werden.
Da ein Listenelement statt eines Werts eines einfachen Datentyps ein Objekt verwaltet, kann man ein solches Listenelement für alle
Objekte in Java verwenden. Werte einfacher Datentypen können unter Verwendung der entsprechenden Wrapper-Klasse in der Liste gespeichert werden.
Die
Verwaltung der Liste wird genauso wie in anderen Sprachen vorgenommen.
Der folgende Auszug zeigt, wie eine Einfüge-Operation mit int-Werten aussieht:
public void add(int value) {
// Neues Listenelement mit dem
// übergebenen Wert erzeugen
ListElement newelement =
new ListElement();
newelement.setObject(new Integer(value));
// Ist die Liste Leer?
if (root != null) {
// Ist der neue Wert größer, als der erste?
if (value > ((Integer)root.getObject()).intValue()) {
ListElement current = root; // Laufzeiger
// Suche Einfügeposition
while((current.getNext() != null) &&
(value > ((Integer)current.getNext().getObject()).intValue()))
current = current.getNext();
// Einfügen in die Liste
newelement.setNext(current.getNext());
current.setNext(newelement);
}
else {
// Einfügen vor 'root', wenn neues Element
// kleiner als das erste Element ist
newelement.setNext(root);
root = newelement;
}
}
else
// Einfügen als 'root', wenn die Liste leer ist
root = newelement;
}
Die Methode add() fügt einer Liste mit aufsteigender Reihenfolge ein neues Element hinzu.
Folgendes Testprogramm liest Zahlen von der Standardeingabe.
Jedes mal, wenn eine Zahl eingegeben wurde, wird sie in die Liste
aufgenommen. Anschließend wird die Liste aufsteigend sortiert ausgegeben.
Gibt man einen Buchstaben ein, wird das Programm beendet.
public static void main(String args[]){
SimpleListDemo demo = new SimpleListDemo();
int number;
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
do {
try {
// Eine Zahl einlesen
number = Integer.parseInt(in.readLine());
demo.add(number); // Zahl der List hinzufügen
stdout.println();
demo.out(); // Gesamte Liste ausgeben
}
catch(Exception e) { // Im Fehlerfall
System.exit(1); // Programm beenden
}
} while(true);
}
Auf diese Weise können nicht nur einfach verkettete Listen, sondern alle anderen
Datenstukturen, wie z. B. Bäume, realisiert werden.
Die Definition von Datenstrukturen über Verkettung ist zwar die flexibelste Technik,
jedoch sollte man vor der Verwendung prüfen, ob nicht bereits eine
Struktur vorhanden ist, die den gewünschten Zweck erfüllt.
Im neuen Java Collection-Framework sind bereits viele Container und Algorithmen
enthalten, die ohne viel Aufwand benutzt werden können.