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.