Grundkurs Informatik. Viele Schränke bilden eine Schrankwand

Ähnliche Dokumente
Objektsammlungen. Programmieren 2. Konzepte (Wiederholung vom Dienstag)

Problem: Was ist, wenn der Stapel voll ist? Idee: Erzeuge dynamisch ein grösseres Array und kopiere um. Dynamische Anpassung der Größe

Aufgabenblatt 4. Aufgabe 3. Aufgabe 1. Aufgabe 2. Prof. Dr. Th. Letschert Algorithmen und Datenstrukturen

JAVA KURS COLLECTION

Einstieg in die Informatik mit Java

ALP II Dynamische Datenmengen Datenabstraktion

Programmierkurs Java

Grundkonzepte java.util.list

Verkettete Listen. Implementierung von einfach verketteten Listen. Implementierung von doppelt verketteten Listen

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 13. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 12. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Listen. Prof. Dr. Christian Böhm. in Zusammenarbeit mit Gefei Zhang. WS 07/08

Lineare Datenstrukturen: Felder, Vektoren, Listen Modelle: math. Folge (a i ) i=1.. mit Basistyp T oder: [T]

Faulheit professionell: Fertige Datenbehälter. Das Java-Collections-Framework Typsicherheit Generische Klassen

Objektorientierte Programmierung. Kapitel 21: Einführung in die Collection Klassen

java.util. Sebastian Draack Department Informations- und Elektrotechnik Department Informations- und Elektrotechnik JAVA Collection-API

OCP Java SE 8. Collections

Software Entwicklung 1

ADT: Java Collections und ArrayList

Einführung in die Objektorientierte Programmierung Vorlesung 18: Lineare Datenstrukturen. Sebastian Küpper

Einführung in die Programmierung mit Java

Info B VL 14: Java Collections/Reflections

Kapitel 6: Java Collection Teil I

Einführung in die Programmierung

Organisatorisches. drei Gruppen Gruppe 1: 10:10-11:40, Gruppe 2: 11:45-13:15 Gruppe 3: 13:20-14:50

Organisatorisches. Neue Übungsblätter: Nur mehr elektronisch? Abgabe Di, , 14 Uhr bis Do, , 8Uhr

Verkettete Datenstrukturen: Listen

Abstrakte Datentypen und Java

19 Collections Framework

Programmierkurs Java

Java Einführung Collections

Gliederung. 5. Compiler. 6. Sortieren und Suchen. 7. Graphen

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

7. Verkettete Strukturen: Listen

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

II.4.4 Exceptions - 1 -

Einführung in die Programmierung

Einführung in die Informatik

Ordnung im Materiallager: Datenstrukturen II. Suchen und Sortieren im Array Verkettete Listen Rekursion

19 Collections Framework

Übungsblatt Programmierung und Software-Entwicklung Generizität, Interfaces, Listen, Sortieralgorithmen & JUnit

12 Collections Framework. Interfaces Maps and Collections. Collection Interface. Überblick. Collection = Containterklasse, die andere Objekte enthält.

Abschnitt 10: Datenstrukturen

Objektorientierung. Marc Satkowski 20. November C# Kurs

IT I: Heute. abstrakte Methoden und Klassen. Interfaces. Interfaces List, Set und Collection IT I - VO 7 1

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Nachtrag: Vergleich der Implementierungen von Stack

12. Dynamische Datenstrukturen

Grundlagen der Informatik 0

13. Dynamische Datenstrukturen

Kapitel 7: Java Collection Teil I

Programmieren 2 16 Java Collections und Generizität

Institut für Informatik

II.4.6 Collections - 1 -

Software Entwicklung 1

Programmieren in Java

Mengen und Multimengen

16. Dynamische Datenstrukturen

Programmieren I. Kapitel 13. Listen

Aufgaben NF 11; Seite 1

ALP II Dynamische Datenmengen Datenabstraktion (Teil 2)

Software Entwicklung 1

Wo sind wir? Rudolf Berrendorf FH Bonn-Rhein-Sieg Programmiersprache Java 338

Collections. Datamining und Sequenzanalyse. Marvin Meusel, Bertram Vogel

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

7. Übung Informatik II - Objektorientierte Programmierung

12 Abstrakte Klassen, finale Klassen und Interfaces

Objektorientierte Programmierung

6. Verkettete Strukturen: Listen

Kapitel 5: Iterierbare Container

Software Entwicklung 1

Mengen und Multimengen

Abiturprüfung Informatik, Grundkurs

Rechtsbelehrung. Java und OOP Das Buch Christian Silberbauer 144

Inner Class. 1 public class OuterClass { 2 private int var; 3 public class InnerClass { 4 void methoda() {}; 5 } 6 public void methodb() {}; 7 }

Bastie Sebastian Ritter. Make Java...

Wie entwerfe ich ein Programm?

Programmieren in Java -Eingangstest-

Heute. Nachbetrachtung Wissensüberprüfung. Sortieren Interface Comparable TreeSet Sortieren von Arrays: Arrays.sort() 3.12.

Kapitel 12: Induktive

Einführung in die Programmierung für NF MI. Übung 04

Nützliche Utility-Klassen des JDK

Institut für Programmierung und Reaktive Systeme. Java 6. Markus Reschke

Kapitel 4: Bäume i. 1. Einleitung. 2. Ein Datenmodell für Listen. 3. Doppelt-verkettete Listen. 4. Bäume. 5. Das Collections-Framework in Java

Teil V. Generics und Kollektionen in Java

Organisatorisches. Folien (u.a.) gibt's auf der Lva-Homepage zum Download

Arrays. Einleitung. Deklarieren einer Array Variablen

Java Schulung. Objektorientierte Programmierung in Java Teil V: Die Java Collection Klassen. Prof. Dr. Nikolaus Wulff

Institut für Programmierung und Reaktive Systeme 17. Juli Programmieren II. Übungsklausur

Sammlungen Listen Mengen Abbildungen Algorithmen Wrapper

Institut fu r Informatik

Lösungsvorschläge zur Nachklausur zum Kurs 1618 Sommersemester 2001 am

Computeranwendung und Programmierung (CuP)

Allgemeine Informatik II SS :30-11:30 Uhr

Transkript:

Viele Schränke bilden eine Schrankwand Das einfache Projekt Schrankwand könnte so erweitert werden, dass die Schrankwand eine beliebige Zahl von Schränken enthalten kann. In diesem Fall brauchen wir statt der Objekte schrank1, schrank2 und schrank3 eine Variable [gesucht ist also ein Datentyp] mit der wir alle Schränke gemeinsam verwalten können, also z.b. eine Liste von Schränken oder ein Array von Schränken. Wir werden uns mehrere Fälle ansehen, zunächst das Beispiel Array. Lösung mit dem Array Unsere Klasse Schrankwand benötigt nun eine Objektvariable zum Speichern der Schränke (wir nennen sie schraenke) und eine integer Variable anzahl, um die Zahl der Schränke zu speichern. Wir nehmen die Deklaration in den Kopf der Klasse auf: private Schrank[] schraenke; private int anzahl; Die nachgestellte eckige Klammer deklariert schraenke als ein Array von Exemplaren der Klasse Schrank. Der Konstruktor sollte nun so verändert werden, dass Schrankwände mit verschiedenen Anzahlen erzeugt werden können. Dazu benötigt er einen Parameter für die Anzahl. Außerdem muss das Array selbst initialisiert werden, anschließend sind noch die Schrankobjekte in gewünschter Anzahl und Position zu erzeugen. Die Änderungen im Konstruktor sind also: public Schrankwand(int anzahl) xposition = 40; yposition = 80; farbe = "blau"; orientierung = 0; istsichtbar = false; int schrankbreite = 60; this.anzahl = anzahl; breite = schrankbreite*anzahl; tiefe = 37; schraenke = new Schrank[anzahl]; for (int i=0;i<anzahl;i++) schraenke[i] = new Schrank(i*schrankbreite, 0, farbe, orientierung, schrankbreite, tiefe); Beachten Sie bitte, dass im Schleifenkopf die richtigen Werte für die Variable i verwendet werden. i wird zunächst auf der Startwert 0 gesetzt, da die erste Position im Array den Index 0 hat, die Zählvorschrift i++ zählt jeweils um 1 weiter und die Laufbedingung, mit der man den Abbruch der Schleife festlegt, muss i< anzahl lauten, da der höchste zulässige Index den Wert anzahl-1 hat. Die zulässigen Indizes gehen also von 0..anzahl-1. Die Änderungen in gibaktuellefigur() sind auch sehr einfacher Art. Hier muss das Einfügen in den GeneralPath über eine Schleife gesteuert werden. protected Shape gibaktuellefigur() Parameter in Variable übernehmen Breite der Schrankwand berechnen Schrankobjekte erzeugen GeneralPath schrankwand = new GeneralPath(); for (int i=0;i<anzahl;i++) schrankwand.append(schraenke[i].gibaktuellefigur(), false); return transformiere(schrankwand); OO Grafik Teil 5 Sammlungs Klassen Seite - 1 Schrankposition berechnen Zugriff auf das Array über den Index

Lösung mit ArrayList Eine ArrayList ist eine Klasse, die List implementiert (s.u.) und uns von JAVA im Paket java.util bereitgestellt wird. Wir müssen sie zunächst importieren. import java.util.arraylist; Im Kopf der Klasse heißt es nun: private ArrayList schraenke; private int anzahl; fügt ein Element der ArrayList hinzu Im Konstruktor ändern sich die erzeugenden Zeilen: schraenke = new ArrayList(); for (int i=0;i<anzahl;i++) schraenke.add( new Schrank(i*schrankbreite, 0, farbe, orientierung, schrankbreite, tiefe)); und bei gibaktuellefigur ändert sich die Zugriffsart 1 : holt ein Element aus der ArrayList protected Shape gibaktuellefigur() GeneralPath schrankwand = new GeneralPath(); for (int i=0;i<anzahl;i++) schrankwand.append(((schrank) schraenke.get(i)).gibaktuellefigur(), false); cast von Objekt auf Schrank return transformiere(schrankwand); Shape davon Zum Problem des notwendigen cast siehe auch den Abschnitt über typisierte Sammlungsstrukturen. 1 In einem hohen Maße unbefriedigend ist die hier noch verwendete und so mögliche Steuerung der Schleife über einen Index. Die bessere Lösung ist das Verwenden eines Iterators. Wie der verwendet wird und dass dahinter ein Entwurfsmuster der Objektorientierung steckt, wird noch untersucht. OO Grafik Teil 5 Sammlungs Klassen Seite - 2

Tradition und Moderne? Das Bemerkenswerte an Arrays selbst ist, dass man viele Speicherplätze unter einem Namen direkt ansprechen kann. Welchen Wert man speziell ansprechen wollte, steuert man über den Index und die Syntax ist arrayname[index]. Arrays stellen einen sehr traditionellen Datentyp der Informatik dar. Das bedeutet, dass viele Programmentwickler daran gewöhnt sind, viel schlimmer: entsprechend bei ihrem Entwurf denken! Betrachtet man die Geschichte von Arrays am Beispiel TURBO PASCAL (heute Delphi), dann findet man eine Begründung für die Bedeutung dieses Typs in der Art der Speicherung von Daten bei TURBO PASCAL. Einfache, weil berechenbare und damit schnelle Datenzugriffe waren nur in einem 64 kbyte großen Speicherbereich möglich, in dem sich daher die Bereiche für statische Arrays befanden. Statisch deswegen, weil ihre Größe schon zur Zeit der Programmübersetzung (compile TP ist eine Compilersprache) bekannt sein musste. Man kann dann leicht aus dem Index und dem Speicherbedarf für ein Element die exakte Position jedes Elementes im Speicher direkt berechnen. Die von JAVA bereit gestellten Sammlungstypen stellen modernere Konstrukte dar. Auch bei ihnen nutzt man das Erkennen von immer wieder auftretenden Anforderungen und das Ausformulieren dieser Anforderungen in einer bzw. mehreren Klassen. Stellt man das Klassendiagramm zur Klasse AbstractCollection dar...... dann fehlen viele der Klassen und wenn man bei der Schnittstelle Collection nachsieht,... Interface Collection All Known Subinterfaces: BeanContext, BeanContextServices, BlockingQueue<E>, List<E>, Queue<E>, Set<E>, SortedSet<E> All Known Implementing Classes: AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList, AbstractSet, ArrayBlockingQueue, ArrayList, AttributeList, BeanContextServicesSupport, BeanContextSupport, ConcurrentLinkedQueue, CopyOnWriteArrayList, CopyOnWriteArraySet, DelayQueue, EnumSet, HashSet, JobStateReasons, LinkedBlockingQueue, LinkedHashSet, LinkedList, PriorityBlockingQueue, PriorityQueue, RoleList, RoleUnresolvedList, Stack, SynchronousQueue, TreeSet, Vector... stellt man fest, dass es für ein Diagramm viel zu viele implementierende Klassen gibt. OO Grafik Teil 5 Sammlungs Klassen Seite - 3

ArrayList was ist das bei JAVA? In der javadoc zu ArrayList heißt es: Die ArrayList ist eine Implementation des List interface, bei dem sich die Größe ändern kann also im Gegensatz zu statischen Arrays. Zusätzlich zu den normalen Anforderungen, die alle Klassen erfüllen müssen, die das List interface implementieren, stellt diese Klasse Methoden zur Veränderung der benötigten Größe im Speicher bereit. In der javadoc wird auf den Zeitaufwand der Methoden eingegangen. Dabei ist von besonderer Bedeutung, dass das Anfügen von Elementen mit der Methode add mit konstantem Zeitbedarf erfolgt, worin der wesentliche Unterschied zu einer LinkedList besteht. Zu einer ArrayList wird die Speicherkapazität (capacity) verwaltet. Deren Verwaltung erfolgt automatisch und es ist für uns im Sinne der Kapselung nicht bekannt, wie das erfolgt. Und die LinkedList? Warum ist der Zeitbedarf bei einer LinkedList höher? Dazu sollte man sich eine grafische Darstellung einer verketteten Liste ansehen (siehe auch Aufgabe unten): Inhalt 1 Inhalt 2 Inhalt 3 Inhalt 4 Man greift auf die Daten sequentiell zu. Beginnend beim Kopf kann man zunächst auf das erste Element zugreifen, es enthält neben den gespeicherten Inhalten eine Information, wo das nächste Element der Liste zu finden ist. So geht es weiter bis zum Ende der Liste, bei dem next nicht existiert, also z.b. auf null verwiesen wird. Will man nun zum zwanzigsten Element, muss man auch auf alle 19 vorher zugreifen. Aufgabe: Berechnen Sie die Anzahl der Schritte, die nötig sind, um eine zunächst leere Liste mit 10 Elementen, 20 Elementen, 100 Elementen usw. zu füllen! Zugriff bei Arrays Wenn wir wirklich ein Array haben, wird hier der Zugriff direkt über den Index erfolgen. Zugriff berechenbar Aufgabe: Inhalt 1 Inhalt 2 Inhalt 3 Inhalt 4 1. Welche Schlüsse über die Art der Realisierung von LinkedList können Sie daraus ziehen, dass diese die Methoden addfirst (...), addlast(...), getfirst() und getlast() anbietet. 2. Korrigieren Sie das o.a. Bild! OO Grafik Teil 5 Sammlungs Klassen Seite - 4

Eine Lösung mit LinkedList? Sie sieht kaum anders aus. Insbesondere verändert sich nicht die Art der in der Schnittstelle angebotenen Zugriffe. Wenn das so ist, sollte man von der konkreten Lösung abstrahieren und das tut die Schnittstelle List! Deswegen: Lösung mit List Bei der Deklaration von schraenke wird nur List vorgegeben. private List schraenke; // *****Kern der Änderung***** Die konkrete Implementation bleibt dann dem Konstruktor überlassen. Nur hier und beim import muss man dann bei einer Änderung der konkret verwendeten Klasse etwas ändern. LinkedList Die Änderungen gegenüber der ArrayList-Version sind nicht sehr groß. Natürlich muss der Import für den Datentyp in import java.util.linkedlist geändert werden. schraenke = new LinkedList(); for (int i=0;i<anzahl;i++) schraenke.add(new Schrank(i*schrankbreite,... )); Der Rest bleibt dann wie oben schon beschrieben genauso wie bei der ArrayList. Wie unwichtig diese Änderung für die Problemlösung ist, merken Sie daran, dass man eigentlich gar nicht wissen muss, was eigentlich ArrayList und LinkedList sind. Diese Problemstellung wird erst bei Anwendungen interessant, bei denen sehr oft auf große Datenbestände zugegriffen werden muss. Typisierte Sammlungsstrukturen Grundsätzlich halten die c Elemente vom Typ Object. Der Sinn dieser Regelung ist, dass sie damit Objekte aller von ihr abgeleiteten Klassen (und das sind eben alle Klassen) halten können. Es gibt zwei Nachteile: 1. Man kann keine elementaren Datentypen verwenden, da diese Daten keine Objekte sind. Will man das, muss man erst ein Element der zugehörigen wrapper- Klasse erzeugen. 2. Will man auf die Elemente einer Sammlungsstruktur zugreifen, muss man einen cast durchführen. Das letzte Problem wurde von SUN durch die Einführung typisierter Sammlungsklassen gelöst. Deklariert man private LinkedList<Schrank> schraenke; und definiert dann mit schraenke = new LinkedList<Schrank>(); dann kann man beim Zugriff schraenke.get(i).gibaktuellefigur(); den cast weglassen. OO Grafik Teil 5 Sammlungs Klassen Seite - 5

Interessant wird's...... erst, wenn man sich mit dem Iterator beschäftigt, da dann nicht nur ein Entwurfsmuster der OO betrachtet werden kann, sondern außerdem auch eine weitere Reduzierung der Unterschiede für weitere Datentypen möglich wird. Wir nutzen dann nicht mehr den bei der LinkedList beschriebenen Zugriff über die Indizes, sondern benutzen den Iterator, der von den Sammlungsklassen bereitgestellt wird. Der Programmtext ändert sich dann bei ArrayList folgendermaßen: notwendiger Import: import java.util.iterator; Schleife: for (Iterator it= schraenke.iterator();it.hasnext();) schrankwand.append(((schrank) it.next()).gibaktuellefigur(), false); Im Schleifenkopf bedeuten die erkennbaren Änderungen Schleifenvariable ist hier der von der Klasse ArrayList bereitgestellte Iterator, den wir durch die Methode iterator() bekommen Laufbedingung ist der Wert der Methode hasnext() Der Iterationsschritt wird durch den Iterator selbst gesteuert; wie er das macht, bleibt ihm selbst überlassen Zugriff auf die Elemente Wir greifen mit der Methode next() auf die Elemente des Iterators zu Der cast durch (Schrank) ist notwendig 2, da der Iterator nur Object zurückliefern kann. Nun sind die Änderungen beim Verwenden anderer Klassen zur Speicherung der Schrankobjekte gering. Probieren Sie außer ArrayList und LinkedList auch Vector, HashSet und TreeSet. Beispiel HashSet: Bei einem Wechsel auf diesen völlig anderen Sammlungstyp wird in der Klasse nur beim import und beim Erzeugen der Klasse HashSet geändert. Alles andere bleibt! Die Vielfalt der möglichen Klassen bleibt verwirrend, wenn man sich nicht ausführlich mit ihren Unterschieden beschäftigt. Insbesondere der Unterschied zwischen Vector und ArrayList ist gering und hat damit zu tun, dass beide eine unterschiedliche Entwicklungsstufe des JAVA Systems darstellen. Vector ist eine ältere Variante, die für JAVA 2 neu implementiert wurde. Der bemerkenswerte Unterschied, dass Vector synchronized ist, macht sich bei den Zugriffen von mehreren threads 3 auf dasselbe Sammlungsobjekt bemerkbar und wird eben nur dann relevant, wenn man mit threads arbeitet. 2 Siehe aber die Anmerkungen zu den typisierten Sammlungsstrukturen. Es gibt ebenso typisierte Iteratoren. 3 threads sind nebenläufige Prozesse. Bei einem laufenden JAVA Programm heißt das, dass mehrere Anwendungskomponenten dadurch quasi gleichzeitig aktiv sind, dass sie sich die Prozessorzeit teilen. Gleichzeitige Zugriffe auf dieselben Daten können dabei zu Inkonsistenzen führen. OO Grafik Teil 5 Sammlungs Klassen Seite - 6

Eine selbst geschriebene Klasse Warteschlange Idee und Vorlage: Guido Krüger in GoTo Java 2 4 Zunächst definieren wir, was die Eigenschaften einer Warteschlange sein sollen. Man kann sich hinten anstellen. Wenn man vorn in der Warteschlange steht, kommt man als nächster dran. Über diese zwingenden Eigenschaften hinaus, bauen wir noch ein: Man kann die Länge der Warteschlange erfahren. Man kann feststellen, ob die Warteschlange leer ist. Man kann die Warteschlange in einem Schritt komplett leeren. Die Warteschlange hat einen Iterator Damit definieren wir eine Schnittstelle, das Interface der Queue-Collection 5. import java.util.iterator; public interface Queue Schnittstellenkopf wie bei Klassen // Gibt true für eine leere queue zurück. public boolean isempty(); // Fügt das Element o am Ende der Queue an. public boolean add(object o); /** * Liefert das erste Element der Queue und entfernt es * daraus. Falls die Queue leer ist, erhält man null. */ public Object retrieve(); // Liefert die Anzahl der Elemente der Queue. public int size(); // Entfernt alle Elemente aus der Queue. public void clear(); // Liefert einen Iterator über alle Elemente der Queue. public Iterator iterator(); Die Klasse Warteschlange implementiert nun diese Schnittstelle, also lautet der Kopf public class Warteschlange implements Queue Für das Realisieren der Verkettungsstruktur bauen wir uns eine einfache Klasse ListenElement. Da sie extern nicht benötigt wird 6, schreiben wir eine innere Klasse (Fachausdruck, auch lokale Klasse). Sie kann das Sichtbarkeitsattribut private haben. private class ListenElement public Object inhalt = null; // Zeiger auf den Inhalt public ListenElement nachfolger = null; // Zeiger auf den Nachfolger 4 In diesem Projekt arbeiten wir noch ohne Exceptions. In einem weiteren Schritt sollten diese eingebaut und besprochen werden. 5 Vergleichen Sie mit dem Collection interface! 6 Über die hier beschriebene Eigenschaft hinaus bieten innere Klassen eine wichtige weitere Eigenschaft gegenüber normalen Klassen: Da sie innerhalb der Umgebung ihrer äußeren Klasse definiert werden, gehören sie zu dieser Umgebung und haben Zugriff auf alle Eigenschaften der äußeren Klasse. Auf die sich daraus ergebenden Möglichkeiten wird hier aber nicht eingegangen. OO Grafik Teil 5 Sammlungs Klassen Seite - 7

An Instanzvariablen benötigen wir: protected ListenElement anfang; protected ListenElement ende; protected int anzahl; Den Zeiger auf den Anfang benötigen wir trivialerweise und zwingend, den auf das Ende nur, um das Anhängen einfach zu realisieren. Auch das Attribut anzahl ist nicht zwingend, es erleichtert aber die Bestimmung von size. Beachten Sie, dass die Elemente in der queue nicht die Inhalte sind, sondern eben Listenelemente. Der Konstruktor initialisiert nur diese Werte standardmäßig (könnte man sich also eigentlich sparen). public Warteschlange() anfang = null; // die Warteschlange ist am Anfang leer. ende = null; anzahl = 0; Die folgenden Methoden sind sehr einfach: public boolean isempty() return anzahl == 0; public int size() return anzahl; Betrachten wir die add Methode etwas genauer, dann stellt man sehr bald fest, dass eine Fallunterscheidung notwendig ist: public boolean add(object o) hat es geklappt? if (isempty()) // Die Schlange ist leer anfang = new ListenElement(); // Ein neues Listenelement wird angelegt ende = anfang; // Das erste Element ist gleichzeitig auch das letzte else // anderenfalls: ende.nachfolger = new ListenElement(); // Ein neues Element wird erzeugt, ende = ende.nachfolger; // und angehängt. ende.inhalt = o; ende.nachfolger = null; anzahl++; return true; // Inhalt wird zugewiesen // Als Ende kennzeichnen // Anzahl wird angepasst. Und das Entfernen: public Object retrieve() if (isempty()) return null; // Hier liegt ein fehlerhafter Zugriff vor // Da der Anfang verändert wird, muss der Inhalt bis zum return gesichert werden Object dasobjekt = anfang.inhalt; anfang = anfang.nachfolger; // Die Schlange rückt auf anzahl--; // Länge korrigieren if (isempty()) // jetzt leer? ende = anfang; return dasobjekt; Nun geht das Leeren sehr einfach: public void clear() while (!isempty()) retrieve(); OO Grafik Teil 5 Sammlungs Klassen Seite - 8

Interessant wird das Erstellen des Iterators. Hier wird eine anonyme Klasse verwendet, also eine Klassendefinition, die keinen Namen bekommt und deswegen auch nur an dieser Stelle ausgeführt werden kann. Bemerkenswert ist insbesondere der Zugriff auf die Variablen und die andere innere Klasse der äußeren Klassendefinition! public Iterator iterator() // Methode von Warteschlange! return new Iterator() // nun kommt seine Definition! ListenElement aktuell = anfang; public boolean hasnext() return aktuell!= null; kann auf die Attribute der äußeren Klasse zugreifen! public Object next() // Die Vorbedingung, ob ein Nachfolger existiert, wird nicht geprüft! Object dernaechste = aktuell.inhalt; aktuell = aktuell.nachfolger; return dernaechste; public void remove() // führt nichts aus! ; // ist ja ein Wert --> Ende vom return! Wie so oft gilt: Das kann man natürlich auch alles ganz anders machen! OO Grafik Teil 5 Sammlungs Klassen Seite - 9

Warteschlangen und Individuen Eine interessante Frage stellt sich, wenn man Warteschlangen nicht unabhängig von einer konkreten Anwendung betrachtet, sondern bei den sich anstellenden Objekten z.b. an Personen denkt. Wir werden dann fordern, dass sich eine Person, die schon in der Schlange steht, nicht noch einmal anstellen kann. Arbeitet man mit mehreren Warteschlangen, wie sie beispielsweise bei einem Supermarkt an der Kasse vorzufinden sind, dann würde man die Anforderungen sogar noch darum erweitern, dass ein Objekt in keiner der Warteschlangen sich zusätzlich anstellen kann. In diesem Fall muss man ernsthaft darüber nachdenken, in welcher Klasse man die Absicherung ansiedelt: Es ist sicher eine Eigenschaft eines konkreten Person Objektes, dass es sich nicht gleichzeitig in zwei oder mehr Warteschlangen befinden kann. Daher könnte man der Person ein Attribut angestellt zuordnen, das dann beim Anstellen und Verlassen der Warteschlange entsprechend verwaltet wird. Aus der Sicht einer einzelnen Warteschlange ist eine Verwaltung mit einer Methode contains(object o) angemessen, die auch intern beim add(object o) verwendet wird. public boolean contains(object o) for (Iterator it=iterator();it.hasnext();) if (it.next()==o) return true; return false; und: public boolean add(object o) if (isempty()) // Ein neues Listenelement wird angelegt anfang = new ListenElement(); // Das erste Element ist gleichzeitig auch das letzte ende = anfang; else // Ein neues Element wird erzeugt, ende.nachfolger = new ListenElement(); // und angehängt ende = ende.nachfolger; if (contains(o)) return false; // keine Wiederholung! else ende.inhalt = o; // Inhalt wird zugewiesen ende.nachfolger = null; // Als Ende kennzeichnen anzahl++; // Anzahl wird angepasst. return true; sets Die Frage, ob man Elemente mehrfach in einer Sammlung vorfinden kann, ist von allgemeinerer Bedeutung und findet sich in einem besonderen Sammlungstyp wieder, den sets. Der Begriff stammt von mathematischen Anwendungen, er bedeutet im Deutschen Menge. In einer Menge kann ein Element höchstens einmal enthalten sein. Dabei ist es übrigens in der Informatik nicht zwingend, dass dies intern auch wirklich so realisiert wird. Es wäre durchaus denkbar, wenn mehrfaches add für dasselbe Objekt nach außen dadurch keine erkennbare Veränderung macht, dass beispielsweise Methoden wie size() nur einmal zählen und bei remove alle entfernt werden. OO Grafik Teil 5 Sammlungs Klassen Seite - 10