Wird ein Array erzeugt, ist seine Größe ab diesem Zeitpunkt unveränderlich. Diese Einschränkung wird in bestimmten Fällen zu einem Problem.
Dies ist zum Beispiel der Fall, wenn zum Zeitpunkt, zu dem ein Array erzeugt werden soll, nicht klar ist, wie viele Objekte maximal verwaltet werden müssen. Die Größe des Arrays müsste dann über die Maßen groß gewählt werden, damit es nahezu ausgeschlossen ist, dass sie einmal nicht ausreicht. Dies führt jedoch dazu, dass das Array in der Regel nur zu einem geringen Teil ausgelastet ist und damit unnötig Speicherplatz reserviert.
Gleiches gilt für den Fall, dass sich eine maximale Größe zwar sinnvoll bestimmen lässt, jedoch vorhersehbar ist, dass die Auslastung stark schwanken wird.
ArrayList
Beispielhaft erarbeiten wir im Folgenden, wie Listen in Java mit Hilfe der Klasse ArrayList realisiert werden können.
Grundsätzlich müssen die Objekte, die in eine ArrayList aufgenommen werden sollen, nicht die gleiche Klasse besitzen. Dies hat jedoch den Nachteil, dass in der Liste alle Objekte unter dem Typ Object, der gemeinsamen Oberklasse aller Objekte in Java, gespeichert werden. Deshalb ist beim Zugriff auf ein Objekt eine Typumwandlung notwendig, um das Objekt wieder in seine jeweilige Unterklasse zu überführen.
Eine ArrayList lässt sich jedoch wesentlich einfacher handhaben, wenn sie angewiesen wird, nur Objekte einer bestimmten Klasse aufzunehmen. Die ArrayList verwaltet die in ihr gespeicherten Objekte dann unter ihrer jeweiligen Klasse. Eine Typumwandlung ist damit nicht mehr erforderlich. Möglich wird dies, da Java in seiner aktuellen Version die Klasse ArrayList in Form einer generischen Klasse bereitstellt.
Beispiel: Nutzung der generischen Klasse ArrayList<E>
Deklaration
Bei der Deklaration einer Variablen vom Typ ArrayList<E> muss der Typ, den die aufzunehmenden Objekte besitzen müssen, anstelle des Typ-Paramteres E zwischen den spitzen Klammern angegeben werden.
Erzeugung
Wird eine Objekt der Klasse ArrayList<E> erzeugt, muss der Typ, den die aufzunehmenden Objekte besitzen müssen, anstelle des Typ-Paramteres E zwischen den spitzen Klammern angegeben werden.
Eine neu erzeugte ArrayList enthält noch keine Elemente und besitzt daher die Größe 0.
Hinzufügen eines Elements
Mit Hilfe der Methode +add(e: E): boolean können der jeweiligen ArrayList<E> Objekte vom Typ E hinzugefügt werden.
Ersetzen eines Elements
Mit Hilfe der Methode +set(index: int, element: E): E kann das Element mit dem Index index der jeweiligen ArrayList<E> durch das Objekt element ersetzt werden. Die Methode gibt als Antwort einen Verweis auf das entfernte Objekt zurück.
Zugriff auf ein bestimmtes Element
Mit Hilfe der Methode +get(index: int): E kann auf das Element mit dem Index index der jeweiligen ArrayList<E> zugegriffen werden.
Entfernen eines Elements
Mit Hilfe der Methode +remove(index: int): E kann das Element mit dem Index index aus der jeweiligen ArrayList<E> entfernt werden. Die Methode gibt als Antwort einen Verweis auf das entfernte Objekt zurück.
Alternativ kann auch die Methode +remove(o: Object): boolean genutzt werden, um das Objekt o aus der jeweiligen ArrayList<E> zu entfernen. Wenn die ArrayList das zu entfernende Objekt enthielt, gibt die Methode true, andernfalls false zurück.
Ermittlung der Größe
Die öffentliche Methode +size(): int gibt die Anzahl der Elemente in der ArrayList zurück.
Aufgabe 15-4: Kurierdienst II
Die in Aufgabe 15-3 geltende Einschränkung, dass jeder Kunde lediglich bis zu dreißig Aufträge erteilen kann, heben wir nun auf. Es soll nun möglich sein, jedem Kunden beliebig viele Aufträge zuweisen zu können.
Aufgaben
Erstellen Sie auf Grundlage des abgebildeten UML-Klassendiagramms (vgl. Abb. 15-24) den Quellcode der Klasse Kunde.
Lösung
Lösung
Erstellen Sie eine Testklasse, in deren main-Methode die folgenden Anweisungen ausgeführt werden:
Erzeugen Sie drei Objekte der Klasse Auftrag mit den Auftragsnummern „A1“, „A2“ und „A3“.
Erzeugen Sie ein Objekt der Klasse Kunde und weisen Sie diesem die Aufträge mit den Auftragsnummern „A1“, „A2“ und „A3“ zu.
Fragen Sie mit Hilfe einer Schleife alle dem Kunden zugewiesenen Aufträge ab und geben Sie dabei von jedem Auftrag Index und Auftragsnummer auf der Konsole aus.
Geben Sie den Text „Erster Auftrag wird gelöscht!“ auf der Konsole aus und entfernen Sie den Auftrag mit dem Index 0 aus der Auftragsliste des Kunden. Fragen Sie anschließend mit Hilfe einer Schleife alle dem Kunden zugewiesenen Aufträge ab und geben Sie dabei von jedem Auftrag Index und Auftragsnummer auf der Konsole aus.
Geben Sie den Text „Das Auftragsobjekt a2 wird gelöscht!“ auf der Konsole aus und entfernen Sie das Auftragsobjekt mit der Auftragsnummer „A1“ aus der Auftragsliste des Kunden. Fragen Sie anschließend mit Hilfe einer Schleife alle dem Kunden zugewiesenen Aufträge ab und geben Sie dabei von jedem Auftrag Index und Auftragsnummer auf der Konsole aus.
Geben Sie die Auftragsnummer des Auftrags mit dem Index 0 auf der Konsole aus. Ersetzen Sie dann das Auftragsobjekt mit dem Index 0 durch das Auftragsobjekt mit der Auftragsnummer „A1“. Geben Sie nach der Änderung die Auftragsnummer des Auftrags mit dem Index 0 auf der Konsole aus.
Die ABC-GmbH erstellt für Ihre Privatkunden Rechnungen entsprechend der in Abbildung 15-27 zu sehenden Beispielrechnung
Beispiel
Aufgaben
Erstellen Sie auf Grundlage der abgebildeten Beispielrechnung (vgl. Abb. 15-27) ein UML-Klassendiagramm. Berücksichtigen Sie dabei, dass eine Rechnung beliebig viele Rechnungspositionen enthalten kann. Vereinfachend können Sie auf die Angabe der set- und get-Methoden verzichten. Methoden, die den Zugriff auf eine Liste erlauben, sowie Methoden, die für die Aufgabe relevante Werte berechnen, sind jedoch anzugeben.
Erstellen Sie den Quellcode der in Teilaufgabe a) modellierten Klassen.
Lösung
Lösung
Testen Sie Ihr Programm, indem Sie in der main-Methode einer Testklasse die im folgenden UML-Objektdiagramm (vgl. Abb. 15-34) dargestellten Objekte erzeugen. Lassen Sie anschließend den Rechnungsbetrag sowie die darin enthaltene Mehrwertsteuer auf der Konsole ausgeben.
Ein Unternehmen möchte wissen, wie hoch seine Umsätze mit Kunden aus einem bestimmten Postleitzahlbereich sind.
Aufgaben
Erstellen Sie die Klasse Kunde, die vereinfachend nur über die Attribute postleitzahl vom Typ String und umsatz vom Typ double sowie entsprechende set- und get-Methoden verfügt. Lösung
Lösung
Erstellen Sie eine Klasse Kundenverwaltung, die das Attribut kundenliste besitzt, das beliebig viele Objekte der Klasse Kunde aufnehmen kann. Fügen Sie außerdem die Methode addKunde(pKunde: Kunde) hinzu, die das Objekt pKunde an die kundenliste anfügt. Weitere Zugriffsmethoden sind nicht erforderlich. Lösung
Lösung
Erstellen Sie in der Klasse Kundenverwaltung die Methode ermittleUmsatz(pPostleitzahl: String): double, die den Umsatz ermittelt, der mit Kunden aus dem Postleitzahlbereich pPostleitzahl erzielt wurde. Lösung
Lösung
Passen Sie die Methode ermittleUmsatz(pPostleitzahl: String): double so an, dass neben einer kompletten Postleitzahl (z. B. 97941) auch nur ein die ersten Stellen (z. B. 97 oder 979) übergeben werden können, um so mehrere Postleitzahlbereiche auszuwählen. Lösung
Lösung
Erstellen Sie eine Testklasse, in deren main-Methode folgende Anforderungen umgesetzt sind:
Erzeugen Sie ein Objekt der Klasse Kundenverwaltung namens kundenverwaltung.
Erzeugen Sie die drei Kunden-Objekte
k1 (Postleitzahl 97941, Umsatz 2000),
k2 (Postleitzahl 97941, Umsatz 4000) und
k3 (Postleitzahl 70173, Umsatz 6000).
Fügen Sie die drei Kunden-Objekte k1, k2 und k3 dem Attribut kundenliste des Objekts kundenverwaltung hinzu.
Rufen Sie die Methode ermittleUmsatz(pPostleitzahl: String): double des Objekts kundenverwaltung auf, übergeben Sie als Parameter den String "97" und geben Sie die Antwort auf der Konsole aus.
Bei Teilaufgabe d) können je nach Lösungsweg folgende Methoden der Klasse String hilfreich sein:
Die Methode substring(beginIndex: int, endIndex: int): String liefert den Teil des jeweiligen Strings zurück, der mit dem Zeichen an Position (Index) beginIndex beginnt und mit dem Zeichen vor Position endIndex endet. Das erste Zeichen eines Strings hat den Index 0.
Die Methode length(): int gibt die Länge des jeweiligen Strings zurück. Dazu ermittelt sie, aus wie vielen Zeichen der String besteht.