Java/List

Aus ZUM-Unterrichten

Erster Implementierungsansatz

  • ??? Wahrscheinlich ist das Positionszähler nicht so gemeint. Er soll anscheinend selbst ein Listenelement sein. Besitzt jemand einen stimmige Quelltext?

Mögliche Interpretation

Realisiert mit ArrayList: <java> import java.util.ArrayList;

public class List { private ArrayList liste; private int positionszeiger;

public List(){

  liste = new ArrayList(); // die Liste ist leer
  positionszeiger=-1; // der Positionszeiger steht vor der Liste

}

public void insertBefore (Object pObject){

  liste.add(positionszeiger, pObject);
  positionszeiger--;

}

public void insertBehind (Object pObject){

  liste.add(positionszeiger+1, pObject);

}

public void update (Object pObject){

  liste.set(positionszeiger, pObject);

}

public void delete (){

  liste.remove(positionszeiger);

}

public void next(){

  if (positionszeiger!=liste.size()) positionszeiger++;

}

public void previous(){

  if (positionszeiger>-1) positionszeiger--;

}

public void toFirst(){

  positionszeiger=0;

}

public void toLast(){

  positionszeiger=liste.size()-1;

}

public Object getItem(){

  if (liste.size()==0 || positionszeiger==-1 || positionszeiger>=liste.size())
    return null;
  else return liste.get(positionszeiger);

}

public boolean isEmpty (){

  return (liste.size()==0);

}

public boolean isBefore (){

  return (positionszeiger<0);

}

public boolean isBehind (){

  return (positionszeiger>=liste.size());

}

} </java>

Korrekturen

11.09. - insertBehind: Positionszeiger wird vor und zurück gestellt http://informatik.zum.de/pieper/blog/index.php?entry=entry060828-105313

Zweiter Implementierungsansatz OOP pur

  • ??? Warscheinlich ist der Positionszeiger aus Delphi entlehnt und nicht sauber auf Java übertragbar. Hier mein Versuch es mit möglichst reinem OOP zu versuchen (bitte auf die Basisklasse ListElement achten.

<java> import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable;

/**

* Bestandteil des Zentralabiturs 2009
*
* Objekte der Klasse List verwalten beliebige Objekte nach einem Listenprinzip. Ein * interner Positionszeiger wird durch die Listenstruktur bewegt, seine Position markiert * ein aktuelles Objekt. Die Lage des Positionszeigers kann abgefragt, verändert und die * Objektinhalte an den Positionen können gelesen oder verändert werden. Die Klasse Stack * stellt Methoden in folgender Syntax zur Verfügung:

*

    *
  • public List()
  • *
  • public boolean isEmpty()
  • *
  • public boolean isBefore()
  • *
  • public boolean isBehind()
  • *
  • public void next()
  • *
  • public void previous()
  • *
  • public void toFirst()
  • *
  • public void toLast()
  • *
  • public Object getItem()
  • *
  • public void update (Object pObject)
  • *
  • public void insertBefore (Object pObject)
  • *
  • public void insertBehind (Object pObject)
  • *
  • public void delete()
  • *
*  Nicht Bestandteil des Zentralabiturs 2009 - dient der praktischen Anwendung

*

    *
  • public clone()
  • *
  • public load(String fileName)
  • *
  • public save(String fileName)
  • *
*
* @author <a href="mailto:schule@dinro.de">DiNaro</a>
* @version 1.0z+ 2006-09-12
*/

public class List implements Cloneable, Serializable { /** * Attribut dient zur Serialisierung. */ private static final long serialVersionUID = 1087406856309777647L; /** * Attribut der Positionszeiger befindet sich vor der Liste (Flag). */ private boolean before;

/** * Attribut der Positionszeiger befindet sich hinter der Liste (Flag). */ private boolean behind;

/** * Attribut aktuelles Element. */ private ListElement current;

/** * Attribut erstes Element der Liste */ private ListElement first;

/** * Attribut letztes Element der Liste. */ private ListElement last;

/** * Der Konstruktor erzeugt eine leere lineare Liste.
*
*

*

	 * Konstruktor   List()
	 * <br>
	 * Nachher       Eine leere Liste ist angelegt.
	 *               Der interne Positionszeiger steht vor der leeren Liste.
	 * 

*/ public List() { this.first = null; this.last = null; this.current = null; this.before = true; this.behind = false; }

/** * Kopiert die Liste - Nicht Bestandteil des Zentralbiturs 2009!!!
* ("shallow copy" nach dem Handbuch der Java Programmierung Kapitel 9.4.2). * * @return kopierte lineare Liste * @throws CloneNotSupportedException kann nicht auftreten, aber der Compiler will es * so... */ @Override public List clone() throws CloneNotSupportedException { try { return (List) super.clone();// "shallow copy" } catch (CloneNotSupportedException e) { // Kann nicht auftreten, aber der Compiler will es so... throw new CloneNotSupportedException(e.toString()); } }

/** * Löscht des aktuellen Listenelement.
*
*

*

	 * Auftrag      delete()
	 * Vorher       Der Positionszeiger steht nicht vor oder hinter der Liste.
	 * Nachher      Das aktuelle Listenelement ist gelöscht. Der Positionszeiger steht auf
	 *              dem Element hinter dem gelöschten Element, bzw. hinter der Liste,
	 *              wenn das gelöschte Element das letzte Listenelement war.
	 * 

*/ public void delete() { if (!this.before && !this.behind) { // Zeiger des Vorgängerelementes setzen if (this.current == this.first) { // Vorgänger existiert nicht - Kopfzeiger korregieren this.first = this.current.getNext(); } else { // Vorgänger existiert this.current.getPrevious().setNext(this.current.getNext()); } // Zeiger des Nachfolgerelementes setzen if (this.current == this.last) { // Nachfolger existiert nicht - Scxhwanzzeiger korreegieren this.last = this.current.getPrevious(); } else { // Nachfolger existiert this.current.getNext().setPrevious(this.current.getPrevious()); } // aktuelles Element setzen this.current = this.current.getNext(); // Flag für Positionszeiger befindet sich hinter der Liste setzen this.behind = this.current == null; } }

/** * Gibt den Inhalt des aktuellen Listenelementes zurück, ohne die Liste zu verändern.
*
*

*

	 * Anfrage       getItem(): Object
	 * Nachher       Die Anfrage liefert den Wert des aktuellen Listenelements bzw. null,
	 *               wenn die Liste keine Elemente enthält, bzw. der Positionszeiger
	 *               vor oder hinter der Liste steht.
	 * 

* * @return item Inhalt des aktuellen Listenelementes. */ public Object getItem() { if (this.current != null) { return this.current.getItem(); } else { return null; } }

/** * Einfügen eines Listenelementes vor das aktuelle.
*
*

*

	 * Auftrag       insertBefore (Object pObject)
	 * Vorher        Der Positionszeiger steht nicht vor der Liste.
	 * Nachher       Ein neues Listenelement mit dem entsprechenden Objekt ist angelegt und
	 *               vor der aktuellen Position in die Liste eingefügt worden.
	 *               Der Positionszeiger steht hinter dem eingefügten Element.
	 * 

* * @param pObject Inhalt des Listenelementes. */ public void insertBefore(Object pObject) { if (!this.before) { // Der Positionszeiger steht nicht vor der Liste. ListElement newElement; if (this.isEmpty()) { // Erstes und einziges Element in die Liste einfügen newElement = new ListElement(pObject, null, null); this.first = newElement; this.last = newElement; this.behind = true; this.current = null; } else { // Die Liste ist nicht leer if (this.behind) { // Der Positionszeiger steht hinter der Liste newElement = new ListElement(pObject, this.last, null); this.last.setNext(newElement); this.last = newElement; this.behind = true; this.current = null; } else { // Der Positionszeiger steht mitten in der Liste newElement = new ListElement(pObject, this.current.getPrevious(), this.current); if (this.current == this.first) { // Vorgänger existiert nicht - Kopfzeiger korregieren this.first = newElement; } else { // Vorgänger koregieren this.current.getPrevious().setNext(newElement); } // Nachfolger korregieren this.current.setPrevious(newElement); // Aktuelles Element bleibt aktuelles Element } } } }

/** * Einfügen eines Listenlementes hinter das aktuelle.
*
*

*

	 * Auftrag       insertBehind (Object pObject)
	 * Vorher        Der Positionszeiger steht nicht hinter der Liste.
	 * Nachher       Ein neues Listenelement mit dem entsprechenden Objekt ist angelegt
	 *               und hinter der aktuellen Position in die Liste eingefügt worden. Der
	 *               Positionszeiger steht vor dem eingefügten Element.
	 * 

* * @param pObject Inhalt des Listenelementes. */ public void insertBehind(Object pObject) { if (!this.behind) { // Der Positionszeiger steht nicht hinter der Liste. ListElement newElement; if (this.isEmpty()) {// Erstes und einziges Element in die Liste einfügen newElement = new ListElement(pObject, null, null); this.first = newElement; this.last = newElement; this.before = true; this.current = null; } else { // Die Liste ist nicht leer if (this.before) { // Der Positionszeiger steht vor der Liste. newElement = new ListElement(pObject, null, this.first); this.first.setPrevious(newElement); this.first = newElement; this.before = true; this.current = null; } else { // Der Positionszeiger steht mitten in der Liste. newElement = new ListElement(pObject, this.current, this.current.getNext()); if (this.current == this.last) { // Nachfolger existiert nicht - Schwanzzeiger korregieren this.last = newElement; } else { // Nachfolger korregieren this.current.getNext().setPrevious(newElement); } // Vorgänger koregieren this.current.setNext(newElement); // Aktuelles Element bleibt aktuelles Element } } } }

/** * Steht der Positionszeiger vor der Liste?
*
*

*

	 * Anfrage       isBefore(): boolean
	 * Nachher       Die Anfrage liefert den Wert true, wenn der Positionszeiger vor dem
	 *               ersten Listenelement oder vor der leeren Liste steht, sonst liefert
	 *               sie den Wert false.
	 * 

* * @return liefert den Wert true, wenn der Positionszeiger vor dem ersten Listenelement * oder vor der leeren Liste steht, sonst liefert sie den Wert false. */ public boolean isBefore() { return this.before; }

/** * Steht der Positionszeiger hinter der Liste?
*
*

*

	 * Anfrage       isBehind(): boolean
	 * Nachher       Die Anfrage liefert den Wert true, wenn der Positionszeiger hinter dem
	 *               letzten Listenelement oder hinter der leeren Liste steht, sonst liefert
	 *               sie den Wert false.
	 * 

* * @return liefert den Wert true, wenn der Positionszeiger hinter dem letzten * Listenelement oder hinter der leeren Liste steht, sonst liefert sie den Wert * false. */ public boolean isBehind() { return this.behind; }

/** * Enthält die Liste keine Elemente?
*
*

*

	 * Anfrage       isEmpty(): boolean
	 * Nachher       Die Anfrage liefert den Wert true, wenn die Liste keine Elemente
	 *               enthält, sonst liefert sie den Wert false.
	 * 

* * @return liefert den Wert true, wenn die Liste keine Elemente enthält, sonst liefert * sie den Wert false. */ public boolean isEmpty() { return this.first == null; }

/** * Lädt die gesamte Liste als Objekt aus einer Datei - Nicht Bestandteil des * Zentralbiturs 2009!!!
* Neues aktuelles Element wird das erste Listenelement(Setzung!). * * @param fileName [Laufwerk][Pfad]Dateiname, * @throws ClassNotFoundException Erwartete Klasse nicht vorhanden * @throws IOException Fehler beim Laden der Datei */ public void load(final String fileName) throws ClassNotFoundException, IOException { try { final ObjectInputStream stream = new ObjectInputStream( new FileInputStream(fileName)); final List dummy = (List) stream.readObject(); this.first = dummy.first; this.last = dummy.last; this.before = dummy.before; this.behind = dummy.behind; this.toFirst(); // Als neues aktuelles Element wird das erste Listenelement gesetzt! stream.close(); } catch (final ClassNotFoundException e) { // Erwartete Klasse nicht vorhanden. throw new ClassNotFoundException(e.toString()); } catch (final IOException e) { // Fehler beim Laden der Datei. throw new IOException(e.toString()); } }

/** * Setze das aktuelle Listenelement auf das nächste.
*
*

*

	 * Auftrag       next()
	 * Nachher       Der Positionszeiger ist um eine Position in Richtung Listenende weiter-
	 *               gerückt, d.h. wenn er vor der Liste stand, wird das Element am
	 *               Listenanfang zum aktuellen Element, ansonsten das jeweils nachfolgende
	 *               Listenelement. Stand der Positionszeiger auf dem letzten Listenelement,
	 *               befindet er sich jetzt hinter der Liste. Befand er sich hinter der
	 *               Liste, hat er sich nicht verändert.
	 * 

*/ public void next() { if (!this.isEmpty()) { if (this.before) { // Der Positionszeiger steht vor der Liste; das erste Element wird aktuelles this.current = this.first; this.before = false; } else { // der Positionszeiger steht nicht vor der Liste if (this.current != null) { // das jeweils nachfolgende Listenelement wird aktuelles this.current = this.current.getNext(); if (this.current == null) { // Der Positionszeiger zeigt hinter das letzte Element this.behind = true; } } } // Der Positionszeiger befindet sich hinter der Liste und bleibt unverändert } }

/** * Setze das aktuelle Listenelement auf das vorherige.
*
*

*

	 * Auftrag       previous()
	 * Nachher       Der Positionszeiger ist um eine Position in Richtung Listenanfang
	 *               weitergerückt, d.h. wenn er hinter der Liste stand, wird das Element am
	 *               Listenende zum aktuellen Element, ansonsten das jeweils vorhergehende
	 *               Listenelement. Stand der Positionszeiger auf dem ersten Listenelement,
	 *               befindet er sich jetzt vor der Liste. Befand er sich vor der Liste, hat
	 *               er sich nicht verändert.
	 * 

*/ public void previous() { if (!this.isEmpty()) { /// Der Positionszeiger bleibt unverändert, wenn die Liste leer ist if (this.behind) { // Der Positionszeiger steht hinter der Liste; das letzte Element wird aktuelles this.current = this.last; this.behind = false; } else {// Der Positionszeiger steht nicht hinter der Liste if (this.current != null) { // das jeweils vorhergehende Listenelement wird aktuelles this.current = this.current.getPrevious(); if (this.current == null) { // Der Positionszeiger zeigt vor das erste Element this.before = true; } } } // Der Positionszeiger befindet sich vor der Liste und bleibt unverändert } }

/** * Speichert die gesamte Liste als Objekt in einer Datei - Nicht Bestandteil des * Zentralbiturs 2009!!!
* Das aktuelles Element bleibt erhalten! * * @param fileName [Laufwerk][Pfad]Dateiname. * @throws IOException Fehler beim Speichern der Datei */ public void save(String fileName) throws IOException { try { ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(fileName)); stream.writeObject(this); stream.close(); } catch (IOException e) { // Fehler beim Speichern der Datei. throw new IOException(e.toString()); } }

/** * Setzt das aktuelle Listenelement auf das erste zurück.
*
*

*

	 * Auftrag       toFirst()
	 * Nachher       Der Positionszeiger steht auf dem ersten Listenelement.
	 *               Falls die Liste leer ist befindet er sich jetzt hinter der Liste.
	 * 

*/ public void toFirst() { this.current = this.first; this.before = false; this.behind = this.isEmpty(); }

/** * Setzt das aktuelle Listenelement auf das letzte zurück.
*
*

*

	 * Auftrag       toLast()
	 * Nachher       Der Positionszeiger steht auf dem letzten Listenelement.
	 *               Falls die Liste leer ist befindet er sich jetzt vor der Liste.
	 * 

*/ public void toLast() { this.current = this.last; this.behind = false; this.before = this.isEmpty(); }

/**

*

	 * Auftrag       update (Object pObject)
	 * Vorher        Die Liste ist nicht leer. Der Positionszeiger steht nicht vor oder
	 *               hinter der Liste.
	 * Nachher       Der Wert des Listenelements an der aktuellen Position ist durch pObject
	 *               ersetzt.
	 * 

* * @param pObject neuer Wert des Listenelements */ public void update(Object pObject) { // Die Liste ist nicht leer. Der Positionszeiger steht nicht vor oder hinter der // Liste. if (!this.isEmpty() && !this.before && !this.behind) { // Die Liste ist nicht leer. Der Positionszeiger steht nicht vor oder hinter der Liste. this.current.setItem(pObject); } }

} ////////////////////////////////// Basisklasse ListElement ///////////////////////////////// import java.io.Serializable;

/**

* Datei ListElement.java (Klasse Listelement mit generalisiertem Datentyp Object).
*
* Die Klasse ListElement ist die Basisklasse für doppelt verkette Listen.
*
* Ein ListElement enthält eine Date, einen Verweis auf den Vorgänger und einen Verweis * auf den Nachfolger.
* * Die Klasse ist wegen der Speicherbarkeit der Oberklasse serialisiert.
* Die Klasse ist nicht Bestandteil des Zentralabiturs 2009, aber notwendig!!! * * @author <a href="mailto:schule@dinro.de">DiNaro</a> * @version 1.0z+ 2006-09-11 */

public class ListElement implements Serializable { /** * Attribut dient zur Serialisierung. */ private static final long serialVersionUID = 8626283657638014888L;

/** * Attribut Date des Listenelements. */ private Object item;

/** * Attribut Nachfolger des Listenelements. */ private ListElement next;

/** * Attribut Vorgänger des Listenelements. */ private ListElement previous;

/** * Der Konstruktor erzeugt ein Listenelement mit Date, Vorgänger und Nachfolger. * * @param item Date des Listenelements. * @param previous Vorgänger des Listenelements * @param next Nachfolger des Listenelemente. */ public ListElement(Object item, ListElement previous, ListElement next) { this.item = item; this.previous = previous; this.next = next; }

/** * Gibt die Date des Elements zurück. * @return Date des Listenelements. */ public Object getItem() { return this.item; }

/** * Gibt den Nachfolger des Listenelements zurück. * @return Nachfolger des Listenelements. */ public ListElement getNext() { return this.next; }

/** * Gibt den Vorgänger des Listenelements zurück. * @return Vorgänger des Listenelements. */ public ListElement getPrevious() { return this.previous; }

/** * Setzt die Date des Listenelements. * @param item neue Date des Listenelements. */ public void setItem(Object item) { this.item = item; }

/** * Setzt den Nachfolger des Listenelements. * @param next neuer Nachfolger des Listenelements. */ public void setNext(ListElement next) { this.next = next; }

/** * Setzt den Vorgänger des Listenelements. * @param previous neuer Vorgänger des Listenelements. */ public void setPrevious(ListElement previous) { this.previous = previous; }

} </java>

Probleme mit der Implementierung

Anwendungsbeispiele

Siehe auch