21 Ve rfe ine rn v o n U ML-Asso ziatio ne n mit de m Java

Werbung
2
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
1
►
JDK Tutorial für J2SE oder J2EE, Abteilung Collections
http://www.oracle.com/technetwork/java/javase/documentation/index.html
Obligatorische Literatur
►
1) Verfeinerung von
Assoziationen
2) Generische Container
3) Polymorphe Container
4) Weitere Arten von Klassen
5) Ungeordnete Collections
6) Kataloge
7) Optimierte Auswahl von
Implementierungen für
Datenstrukturen
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Version 14-0.4, 03.05.14
TU Dresden
Fakultät für Informatik
Lehrstuhl Softwaretechnologie
Institut für Software- und
Multimediatechnik
Prof. Dr. rer. nat. Uwe Aßmann
21) Verfeinern von UML-Assoziationen mit
dem Java-2 Collection Framework
3
4
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
http://download.oracle.com/javase/6/docs/
Tutorials http://download.oracle.com/javase/tutorial/
Generics Tutorial:
http://download.oracle.com/javase/tutorial/extra/generics/index.html
■
Im Wesentlichen sind die Dokumentationen aller Versionen von Java 6 an
nutzbar:
►
►
►
Beispiel “Kataloge mit Maps”
Katalog-Mit-Abbildung/Katalog.java
Katalog-Mit-Abbildung/Katalog2.java
Beispiel “Warengruppen mit Mengen”
Warengruppe-Mengen/Warengruppe0.java
..
Warengruppe-Mengen/Warengruppe4.java
Beispiel "Bestellung mit Listen":
Bestellung-Collections/Bestellung0.java
..
Bestellung-Collections/Bestellung4.java
Über die Homepage der Lehrveranstaltung finden Sie verschiedene JavaDateien dieser Vorlesung.
Hinweis: Online-Ressourcen
►
►
►
►
Empfohlene Literatur
ut
6
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
5
►
►
TestTestTreiber
Treiber
Test-Umgebung
Eingabedaten
Programm
Programm
(SUT)
(SUT)
Ausgabe-Netz
(Ist)
NetzNetzKomparator
Komparator
Ausgabe-Netz (Soll)
Solange
Solangeein
einProgramm
Programmkeine
keineTests
Testshat,
hat,ist
istes
eskeine
keineSoftware
Software
Testen beinhaltet die Ist-Soll-Analyse für Objektnetze
Stimmt mein Netz mit meinem Entwurf überein?
Objektorientierte Software hat eine testgetriebene Architektur für Objektnetze
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.1 Verfeinern von
Assoziationen
Ok
Error
7
8
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Strange-null-pointer-exception-The-Official-Microsoft-ASP.pdf
Bitte mal nach “strange null pointer exception” suchen:
https://forums.oracle.com/forums/thread.jspa?threadID=2056540
http://stackoverflow.com/questions/8089798/strange-java-string-array-nullpointer-exception
Schon mal 3 Tage nach einem Zeiger-Fehler (pointer error) gesucht?
+ preis(): int
+ preis(): int
1
*
Artikel
– name: String
– preis: int
für
Artikel
– name: String
– preis: int
1
*
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
für
Bestellposition
– anzahl: String
– preis: int
1
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
1
*
<<interface>>
Array
1 {ordered}
Online:
Bestellung0.java
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Modell einer Bestellungsabwicklung, eines einfachen Objektnetzes (Hierarchie):
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
►
Verfeinern von Assoziationen (Netzverfeinerung)
►
►
►
►
Warum ist das wichtig?
9
Bestellung0.java
public
public void
void sonderpreis
sonderpreis (int pos, int preis) {{
liste[pos].einzelpreis(preis);
liste[pos].einzelpreis(preis);
}}
public
public int
int auftragssumme()
auftragssumme() {
int
int ss = 0;
0;
for(int
for(int i=0; i<anzahl; i++)
i++) ss +=
+= liste[i].positionspreis();
liste[i].positionspreis();
return
return s;
}}
Online:
Bestellung("TUD");
Bestellposition(tisch,1));
Bestellposition(stuhl,4));
Bestellposition(schrank,2));
Bestellung fuer Kunde TUD
0. 1 x Tisch Einzelpreis: 200 Summe: 200
1. 4 x Stuhl Einzelpreis: 100 Summe: 400
2. 2 x Schrank Einzelpreis: 300 Summe: 600
Auftragssumme: 1200
Bestellung b1 = new
b1.neuePosition(new
b1.neuePosition(new
b1.neuePosition(new
b1.print(); ...}
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Testprogramm für Anwendungsbeispiel (1)
}}
String
String kunde;
kunde;
Bestellposition[]
Bestellposition[] liste;
liste;
int
anzahl
=
0;
int anzahl = 0;
public
public Bestellung(String
Bestellung(String kunde)
kunde) {{
this.kunde
=
kunde;
this.kunde
kunde;
liste
liste == new
new Bestellposition[20];
Bestellposition[20];
}}
public
public void
void neuePosition
neuePosition (Bestellposition
(Bestellposition b)
b) {{
liste[anzahl]
liste[anzahl] == b;
b;
anzahl++;
//
anzahl++;
// was
was passiert
passiert bei
bei mehr
mehr als
als 20
20 Positionen
Positionen ??
}}
public
public void
void loeschePosition
loeschePosition (int
(int pos)
pos) {{
//
// geht
geht mit
mit Arrays
Arrays nicht
nicht einfach zu
zu realisieren
realisieren !
}}
private
private
private
private
private
private
class
class Bestellung {
Einfache Realisierung mit Arrays –
Was ist problematisch?
Online:
Bestellung0.java
10
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
11
12
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Fest zur Allokationszeit
–
Automatisches Verschieben bei Löschen und Mitten-Einfügen
–
Antwort 2: durch Abbildung auf die Schnittstelle Collection
►
Viele Algorithmen laufen auf sortierten Universen wesentlich schneller als auf
unsortierten (z.B. Anfragen in Datenbanken)
Wie bilde ich einseitige Assoziationen aus UML auf Java ab?
–
Was passiert, wenn keine Ordnung benötigt wird?
Kann das Array sortiert werden?
http://en.wikipedia.org/wiki/Dynamic_array
–
Dynamische Arrays sind dynamisch erweiterbar:
Fest zur Übersetzungszeit
–
Java Arrays besitzen eine feste Obergrenze für die Zahl der enthaltenen
Elemente
►
►
►
►
►
Probleme der Realisierung von Assoziationen mit
Arrays
Bestellung
Bestellungfuer
fuerKunde
KundeTUD
TUD
0.0.11xxTisch
Einzelpreis:
Tisch Einzelpreis:200
200Summe:
Summe:200
200
1.1.44xxStuhl
Einzelpreis:
50
Summe:
200
Stuhl Einzelpreis: 50 Summe: 200
2.2.22xxSchrank
SchrankEinzelpreis:
Einzelpreis:300
300Summe:
Summe:600
600
Auftragssumme:
1000
Auftragssumme: 1000
public static void main (String[] args) {
...
b1.sonderpreis(1,50);
b1.print();
}
Testprogramm für Anwendungsbeispiel (2)
13
14
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Verwendung von Vererbung zur Strukturierung
Flexibel auch zur eigenen Erweiterung
–
–
Antwort: Einziehen von Behälterklassen (collections) aus dem CollectionFramework
Flachklopfen (lowering) von Sprachkonstrukten: Wir klopfen Assoziationen zu
Java-Behälterklassen flach.
–
–
Zentrale Frage: Wie bilde ich einseitige Assoziationen aus UML flexibel
auf Java ab?
Meiste Standard-Datenstrukturen abgedeckt
–
Probleme werden durch das Java-Collection-Framework gelöst, eine
objektorientierte Datenstrukturbibliothek für Java
+ preis(): int
+ preis(): int
1
*
Artikel
– name: String
– preis: int
für
Artikel
– name: String
– preis: int
1
*
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
für
Bestellposition
– anzahl: String
– preis: int
1
*
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Ersetzen von “*”-Assoziationen durch Behälterklassen
<<interface>>
Collection
1 {ordered}
Bsp.: Verfeinern von bidir. Assoziationen durch
Behälterklassen
►
►
Collections
15
16
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Online:
Bestellung2LinkedList.java
►
►
Hilfsmittel:
●
Typisierung weglassen
●
Ev. dynamische Typisierung, damit Fehler
zur Laufzeit identifiziert werden können
●
Mächtige Operationen einer Skriptsprache
–
Java
1.6
Mehr Entwurfswissen aus dem Entwurf in die Implementierung übertragen
Hilfsmittel:
●
Statische Typisierung, damit der Übersetzer viele Fehler entdeckt
●
Generische Klassen
Aus der Definition einer Datenstruktur können Bedingungen für ihre Anwendung
abgeleitet werden
Generische Collections für typsicheres Aufbauen von Objektnetzen (Java)
–
–
–
–
Zuverlässigkeit
Java
groovy
Guten, stabilen, wartbaren Code schreiben
Zeit
–
Safe Application Development (SAD)
Schneller viel Code schreiben
–
Rapid Application Development (RAD)
Orthogonale Trends in der Softwareentwicklung
}}
public
public Bestellung(String kunde) {{
this.kunde
this.kunde == kunde;
liste
liste == new
new LinkedList<Bestellposition>(); //
// Erklärung
Erklärung später
später
}
public
public void
void neuePosition (Bestellposition
(Bestellposition b)
b) {
liste.set(anzahl,b);
liste.set(anzahl,b);
anzahl++;
//
anzahl++;
// was
was passiert
passiert jetzt
jetzt bei
bei mehr
mehr als
als 20
20 Positionen ??
}
public
public void
void loeschePosition
loeschePosition (int pos)
pos) {
liste.remove(pos);
liste.remove(pos);
}
public
public void
void sonderpreis
sonderpreis (int
(int pos,
pos, int
int preis) {
liste.get(pos).einzelpreis(preis);
liste.get(pos).einzelpreis(preis);
}
public
public int
int auftragssumme() {{
int
s
int s == 0;
0;
for(int
for(int i=0;
i=0; i<anzahl; i++) s +=
+= liste.get(i).positionspreis();
liste.get(i).positionspreis();
return
return s;
s;
}
class
class Bestellung
Bestellung {{
private
private String
String kunde;
private
private List<Bestellposition>
List<Bestellposition> liste;
liste;
private
int
anzahl
=
0;
private int anzahl = 0;
Einfache Realisierung mit Collection-Klasse “List”
18
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
17
Bestellung
Lieferschein
Formular
Rechnung
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Generische Behälterklassen
Collection<Object>
Bsp.: Elemente einer Hierarchie


21.2 Die Collection-Bibliothek
19
20
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
List<Lieferschein>
List<Rechnung>
mit Duplikaten
ohne Duplikate
geordnet
ungeordnet
sortiert
unsortiert
Sortierung
mit Schlüssel
ohne Schlüssel
Schlüssel
Facetten sind orthogonale Dimensionen einer Klassifikation oder eines
Modells
Duplikate
–
Behälterklassen können anhand von verschiedenen Facetten klassifiziert
werden
Ordnung
►
Facetten von Behälterklassen (Collections)
List<Bestellung>
List<Formular>
Bsp.: Hierarchie von Listen
21
<<interface>>
SortedSet
Sortierung
<<interface>>
Set
Duplikate
<<interface>>
SortedMap
<<interface>>
Map
Schlüssel
TreeSet
HashMap
TreeMap
<<interface>>
SortedMap
<<interface>>
Map
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet
<<interface>>
Set
HashSet
Implementierungsklassenschicht
LinkedList
ArrayList
<<interface>>
List
<<interface>>
Collection
Schnittstellen und Implementierungen im unsicheren,
ungetypten Collection-Framework (vor Java 1.5)
/home/ua1/Courses/ST1/Material/jdk-docs/index.html
<<interface>>
List
Ordnung
<<interface>>
Collection
Java Collection Framework:
Prinzipielle Struktur
Schnittstellenschicht
22
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
23
24
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Programmierfehler!
Laufzeitfehler!!
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
listOfRechnung.add(best);
listOfRechnung.add(best);
Bei der Konstruktion von Collections werden oft Fehler programmiert, die bei
der Dekonstruktion zu Laufzeitfehlern führen
Kann in Java < 1.5 nicht durch den Übersetzer entdeckt werden
ArrayList
add(Object o)
get(pos: int): Object
...
Zusicherung:
Zusicherung:Alle
Allevom
vomObjekt
Objekterreichbaren
erreichbarenObjekte
Objekte
sind
sindaus
ausder
derKlasse
KlasseRechnung.
Rechnung.
listOfRechung:List
*
Rechnung
*
Object
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
Cast nötig, obwohl
alles Rechnungen
Diesmal ok
Bei der Dekonstruktion von Collections müssen unnötig Typumwandlungen
(Casts) spezifiziert werden
Typisierte Collections erhöhen die Lesbarkeit, da sie mehr Information geben
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Rechnung rechnung2 = new Rechnung();
Rechnung rechnung2 = new Rechnung();
listOfRechnung.add(rechnung2);
listOfRechnung.add(rechnung2);
►
►
Problem 2 ungetypter Schnittstellen: Unnötige
Casts
►
►
Problem 1 ungetypter Schnittstellen: Laufzeitfehler
25
26
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
In UML
E
Collection<E>
content
E
–
Sprachregelung: “Collection of E”
In Java
}
E content[];
class Collection<E> {
►
►
List
–
E
SortedSet
Set
Collection
E
E
E
E: Element, K: Key, V: Value
Blocking
Queue
Queue
E
E
K,V
SortedMap
Map
K,V
Die generische Schnittstellen-Hierarchie der Collections (seit Java 1.5)
Collection-Hierarchie mit generischen
Schnittstellen
Collection
►
Eine generische Behälterklasse ist eine Klassenschablone einer
Eine generische Behälterklasse ist eine Klassenschablone einer
Behälterklasse, die mit einem Typparameter für den Typ der
Behälterklasse, die mit einem Typparameter für den Typ der
Elemente versehen ist.
Elemente versehen ist.
Generische Behälterklassen
28
List
<Formular>
E
Queue
<Formular>
Blocking
Queue
<Formular>
SortedSet
<Formular>
Set
E
E
SortedMap
<Nr,Formular>
Map
<Nr,Formular>
SortedSet
<<instantiates>>
Set
<Formular>
Collection
<Formular>
List
Collection
E
►
E
E
K,V
SortedMap
K,V
Darf man Rechnungen,
Bestellungen und
Lieferscheine in diese
Collections stecken?
Ja.
Blocking
Queue
Queue
Map
TreeMap<K,V>
Instanziierung der generischen Hierarchie
TreeSet<E>
HashMap<K,V>
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet<E>
<<interface>>
Set<E>
HashSet<E>
Implementierungsklassenschicht
LinkedList<E>
ArrayList<E>
<<interface>>
List<E>
<<interface>>
Collection<E>
Schnittstellen und Implementierungen im CollectionFramework bilden generische Behälterklassen
Schnittstellenschicht
27
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
29
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
30
Bei der Konstruktion von Collections werden jetzt Äpfel von Birnen
unterschieden
Casts sind nicht nötig, der Übersetzer kennt den feineren Typ
Das ist Safe Application Development (SAD)
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.2.2 Schnittstellen im Detail
Kein Cast mehr nötig
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = listOfRechnung.get(i);
rechnung = listOfRechnung.get(i);
}
}
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
Compilerfehler
listOfRechnung.add(best);
listOfRechnung.add(best);
►
►
►
SAD löst Probleme
31
32
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
}
// Zustandsveränderer
+ boolean remove (E o);
+ void clear();
// Monotone Zustandsveränderer
+ boolean add (E o);
// Repräsentations-Trans// formierer
+ E[] toArray();
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
<<interface>>
Collection<E>
}
...
public int indexOf (E o);
public E remove (int index);
public E set (int index, E element);
public E get (int index);
public void clear();
public boolean remove (E o);
public boolean add (E o);
public int size();
public boolean contains (E o);
public boolean isEmpty();
public interface List extends Collection {
// Zustandsveränderer
+ E remove (int index,E o);
+ E set (int index, E o);
+ int indexOf (E o);
// Query methods
+ E get(int index);
<<interface>>
List
<<interface>>
Collection
Unterschnittstelle java.util.List (Auszug)
…
public void clear();
public boolean remove (E o);
// Nicht-Monotone Zustandsveränderer
public boolean add (E o);
// Monotone Zustandserweiterer
// Zustandsveränderer
public E[] toArray();
// Repräsentations-Transformierer
public Iterator iterator();
public int hashCode();
public int size();
public boolean equals(E o);
public boolean contains (E o);
public boolean isEmpty();
// Anfragen (Queries)
public interface Collection<E> {
Schnittstelle
java.util.Collection (Auszug)
33
35
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Spezifische Schnittstellen sowie
konkrete Implementierungen in der
Collection-Hierarchie können
spezialisiertes Verhalten aufweisen.
Bsp.: Was ändert sich bei Set im
Vergleich zu List in der Semantik
von add()?
// Zustandsveränderer
+ boolean add (E o);
<<interface>>
Set
<<interface>>
Collection
+ preis(): int
+ preis(): int
1
*
Artikel
– name: String
– preis: int
für
Artikel
– name: String
– preis: int
1
*
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
für
Bestellposition
– anzahl: String
– preis: int
1
1 {ordered}
*
<<interface>>
List<Bestellposition>
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Ersetzen von “*”-Assoziationen durch Behälterklassen
Verfeinern von bidir. Assoziationen durch
getypte Behälterklassen
►
►
Unterschnittstelle java.util.Set (Auszug)
36
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
37
}}
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Siedersleben/Denert,
Siedersleben/Denert,
Wie
Wiebaut
bautman
manInformationssysteme,
Informationssysteme,
Informatik-Spektrum
Informatik-Spektrum, ,August
August2000
2000
"Der
"DerAufrufer
Aufruferprogrammiert
programmiertgegen
gegendie
die
Schnittstelle,
Schnittstelle,
er
erbefindet
befindetsich
sichsozusagen
sozusagenim
imluftleeren
luftleerenRaum."
Raum."
21.3 Programmieren gegen Schnittstellen
von polymorphen Containern
public
public Bestellung(String kunde) {{
this.kunde
this.kunde == kunde;
liste
liste == new
new LinkedList<Bestellposition>();
//
// Konkrete
Konkrete Implementierungsklasse
Implementierungsklasse
}
public
public void
void neuePosition (Bestellposition
(Bestellposition b)
b) {
liste.set(anzahl,b);
liste.set(anzahl,b);
anzahl++;
//
anzahl++;
// was
was passiert
passiert jetzt
jetzt bei
bei mehr
mehr als
als 20
20 Positionen ??
}
public
public void
void loeschePosition
loeschePosition (int pos)
pos) {
liste.remove(pos);
liste.remove(pos);
}
public
public void
void sonderpreis
sonderpreis (int
(int pos,
pos, int
int preis) {
liste.get(pos).einzelpreis(preis);
liste.get(pos).einzelpreis(preis);
}
public
public int
int auftragssumme() {{
int
int ss == 0;
0;
for(int
for(int i=0;
i=0; i<anzahl; i++) s +=
+= liste.get(i).positionspreis();
liste.get(i).positionspreis();
return
return s;
s;
Online:
}
Bestellung2LinkedList.java
class
class Bestellung
Bestellung {{
private
private String
String kunde;
private
private List<Bestellposition>
List<Bestellposition> liste;
liste;
private
int
anzahl
=
0;
private int anzahl = 0;
Wdh. Einfache Realisierung mit Collection-Klasse
“List”
39
TreeMap<K,V>
►
►
►
►
Algebraische Spezifikationen
●
Axiomensysteme
Interfaces
–
–
List
Beispiel:
Abstrakte Klassen
–
Praxis:
–
►
►
►
Ausführbare Operationen
Instantiierbare Klassen
Komplexität
–
Alternativen
Verkettete Liste (LinkedList)
Liste durch Feld (ArrayList)
–
–
Beispiel:
–
Praxis:
Datenstrukturen
–
Theorie:
–
Verhalten der Operationen
–
Theorie:
–
Konkretisierung:
Operationen
►
Konkreter Datentyp
(Implementierung)
–
Abstraktion:
Abstrakter Datentyp
(Schnittstelle)
Polymorphie – zwischen abstrakten und
konkreten Datentypen
TreeSet<E>
HashMap<K,V>
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet<E>
<<interface>>
Set<E>
HashSet<E>
Implementierungsklassenschicht
LinkedList<E>
ArrayList<E>
<<interface>>
List<E>
<<interface>>
Collection<E>
Schnittstellen und Implementierungen im CollectionFramework bilden generische Behälterklassen
Schnittstellenschicht
38
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
40
41
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
List<Bestellposition>
ist ein Interface,
keine Klasse !
public Bestellung(String kunde) {
this.kunde = kunde;
this.liste = new LinkedList<
Bestellposition>();
} ...
Bei polymorphen Containern muß der Code bei Wechsel der
Datenstruktur nur an einer Stelle im Konstruktor geändert werden!
public Bestellung(String kunde) {
this.kunde = kunde;
this.liste = new ArrayList<
Bestellposition>();
} ...
!
+ LinkedList<E>();
+ addFirst(E o)
+ addLast(E o)
class
class Bestellung
Bestellung {{
private
private String
String kunde;
kunde;
private
private List<Bestellposition>
List<Bestellposition> liste;
liste;
...
//
Konstruktor
s.
u.
... // Konstruktor s. u.
public
public void
void neuePosition
neuePosition (Bestellposition
(Bestellposition b)
b) {{
liste.add(b);
}}
liste.add(b);
public
public void
void loeschePosition
loeschePosition (int
(int pos)
pos) {{
liste.remove(pos);
}}
liste.remove(pos);
public
public void
void sonderpreis
sonderpreis (int
(int pos,
pos, int
int preis)
preis) {{
liste.get(pos).einzelpreis(preis);
}}
liste.get(pos).einzelpreis(preis);
-- Polymorphe Container
<<interface>>
List<E>
LinkedList<E>
Programmieren gegen Schnittstellen
+ ArrayList<E>(int initialCapacity);
+ void ensureCapacity
(int minCapacity);
ArrayList<E>
public class ArrayList<E> implements List<E> {
public ArrayList<E> (int initialCapacity);
public void ensureCapacity (int minCapacity);
...
}
public class LinkedList<E> implements List<E> {
public void addFirst (E o);
public void addLast (E o);
...
}
Beispiel: Implementierungsklassen
java.util.ArrayList, LinkedList
42
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
43
Iteration
3850
12200
9110
16250
Einfügen
-500
110
550
Entfernen
-46850
60
46850
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.4) Weitere Arten von Klassen und
Methoden
Lesen
1430
3070
16320
4890
Gemessener relativer Aufwand für Operationen auf Listen:
(aus Eckel, Thinking in Java, 2nd ed., 2000)
Innere Schleifen bilden die „heißen Punkte“ (hot spots) eines Programms
Typ
array
ArrayList
LinkedList
Vector
►
►
Aus
Ausalternativen
alternativenImplementierungen
Implementierungeneiner
einerSchnittstelle
Schnittstellewählt
wähltman
mandiejenige,
diejenige,die
diefür
für
das
dasBenutzungsprofil
Benutzungsprofilder
derOperationen
Operationendie
diegrößte
größteEffizienz
Effizienzbereitstellt
bereitstellt
(Geschwindigkeit,
(Geschwindigkeit,Speicherverbrauch,
Speicherverbrauch,Energieverbrauch)
Energieverbrauch)
Welche Listen-Implementierung soll man
wählen?
44
45
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
+ LinkedList<E>();
+ addFirst(E o)
+ addLast(E o)
Tester
Checker
Zustandsinvariante
Methoden
Zustandsmodifikatoren
Netzmodifikatoren
RepräsentationsWechsler
ManagementMethoden
Zustandsverändernde
Methoden
Modifikatoren
(Mutatoren)
Methode
Optimierer
Allgemeine
Methoden
LinkedList<E>
<<interface>>
List<E>
Erweiterung: Taxonomie der Methodenarten
+ ArrayList<E>(int initialCapacity);
// Management-Methode
+ void ensureCapacity
(int minCapacity);
ArrayList<E>
public class ArrayList<E> implements List<E> {
public ArrayList<E> (int initialCapacity);
// Management-Methode (Optimierer-Methode)
public void ensureCapacity (int minCapacity);
...
}
public class LinkedList<E> implements List<E> {
public void addFirst (E o);
public void addLast (E o);
...
}
Management-Methoden in
java.util.ArrayList, LinkedList
Anfrage (query)
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
46
47
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Generische Klasse
Schnittstelle
(interface)
Abstrakte Klasse
Partielle
Klasse
Klasse
Algorithmenklasse
(Konkrete) Klasse
Begriffshierarchie von Klassen (Erweiterung)
file://localhost/Users/ua1/Courses/ST1/Material/jdk-docs/api/java/util/Collections.html
public
public class
class Collections<E>
Collections<E> {{
public
public static
static EE max
max (Collection<E>
(Collection<E> coll);
coll);
public
static
E
min
(Collection<E>
coll);
public static E min (Collection<E> coll);
public
public static
static int
int binarySearch(List<E>
binarySearch(List<E> list,
list, EE
key);
key);
public
public static
static void
void reverse
reverse (List<E>
(List<E> list);
list);
public
static
void
sort
(List<E>
list)
public static void sort (List<E> list)
...
...
}}
Algorithmenklassen
Algorithmenklassen(Hilfsklassen)
(Hilfsklassen)enthalten
enthaltenAlgorithmen,
Algorithmen,
die
auf
einer
Familie
von
anderen
Klassen
arbeiten
die auf einer Familie von anderen Klassen arbeiten
Standardalgorithmen in der Algorithmenklasse
java.util.Collections
48
49
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Clonable
Serializable
–
–
Resultat ist kleiner/gleich/größer 0:
genau dann wenn "this" kleiner/gleich/größer als Objekt o
public
public interface
interface Comparable<E>
Comparable<E> {{
public
public int
int compareTo
compareTo (E
(E o);
o);
}}
Beispiel: geordnete Standarddatentypen (z.B. String oder List)
implementieren die Prädikatschnittstelle Comparable:
Iterable
–
Prädikat-Schnittstellen drücken bestimmte Eigenschaft einer Klasse aus.
Sie werden oft mit dem Suffix “able” benannt:
Prädikatschnittstellen können für einen Typparameter einfache Prädikate
ausdrücken
Beispiel: Comparable<E> als Return-typ in der Collections-Klasse sichert zu,
dass die Methode compareTo() existiert
public static <E extends Comparable<E>> min(Collection<E> ce) {
public static <E extends Comparable<E>> min(Collection<E> ce) {
Iterator<E> iter = ce.iterator();
Iterator<E> iter = ce.iterator();
E curMin = iter.next;
E curMin = iter.next;
if (curMin == null) return curMin;
if (curMin == null) return curMin;
for (E element = curMin;
for (E element = curMin;
iter.hasNext(), element = iter.next) {
iter.hasNext(), element = iter.next) {
if (element.compareTo(curMin) < 0) {
if (element.compareTo(curMin) < 0) {
curMin = element;
curMin = element;
}
}
}
}
return curMin;
return curMin;
}
}
class Collections {
class Collections {
/** minimum function for a Collection. Return value is typed
/** minimum function for a Collection. Return value is typed
* with a generic type with a type bound */
* with a generic type with a type bound */
►
►
Typschranken generischer Parameter (type
bounds), mit Prädikatsschnittstellen
►
►
►
Prädikat-Schnittstellen (...able Schnittstellen)
50
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
51
Prädikat-Schnittstelle
Schnittstelle
(interface)
Abstrakte Klasse
Algorithmenklasse
(Konkrete) Klasse
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.5 Ungeordnete Collections
mit Set
Generische Klasse
Partielle
Klasse
Klasse
Begriffshierarchie von Klassen (Erweiterung)
52
53
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
E
E
K,V
TreeMap<K,V>
TreeSet<E>
HashMap<K,V>
K,V
E
HashSet<E>
E
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
<<interface>>
Collection<E>
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
// Zustandsveränderer
+ boolean add (E o);
// Query methods
+ E get(int index);
<<interface>>
Set<E>
Ungeordnete Mengen: java.util.Set<E> (Auszug)
LinkedList<E>
ArrayList<E>
E
<<interface>>
Set<E>
<<interface>>
List<E>
<<interface>>
SortedSet<E>
E
E
<<interface>>
Collection<E>
E
Mengen (ohne Mehrfacheintrag)
im Collection Framework
54
+ preis(): int
Artikel
– name: String
– preis: int
* {unordered}
+ add (a: Artikel)
+ anzahl(): int
1
Warengruppe
– name: String
– lagerplatz: String
<<interface>>
Collection<E>
(Anmerkung: Erläuterung von Hashfunktionen
folgt etwas später !)
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
<<class>>
HashSet<E>
// Zustandsveränderer
+ boolean add (E o);
// Konstruktor
# HashSet<E>(int initialCapacity,
float loadFactor);
+ E get(int index);
+ int hashCode()
// Zustandsveränderer
+ boolean add (E o);
// Query methods
+ E get(int index);
<<interface>>
Set<E>
Set<E>
Eine Assoziation in UML kann als {unordered} gekennzeichnet sein
Konkreter Datentyp
java.util.HashSet<E> (Auszug)
►
Anwendungsbeispiel für Set<E>
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
55
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
56
57
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Online:
Warengruppe0.java
►
►
Typischer Fehler: Stringvergleich mit "=="
(ist nicht korrekt, geht aber meistens gut!)
–
bei Bedarf selbst überdefinieren !
●
(Ggf. für kompatible Definition der Operation o.hashCode() aus
java.lang.Object sorgen)
Standardbedeutung Referenzgleichheit
●
für selbstdefinierte Klassen
z.B. java.lang.String
überdefiniert in vielen Bibliotheksklassen
–
●
deklariert in java.lang.Object
–
Alternative: Vergleich mit Gleichheitsfunktion o.equals():
–
Der Vergleich mit Operation == prüft auf Referenzgleichheit, d.h.
physische Identität der Objekte
Duplikatsprüfung für Elemente in Mengen:
Wann sind Objekte gleich? (1)
}
public String toString() {
String s = "Warengruppe "+name+"\n";
Iterator it = inhalt.iterator();
while (it.hasNext()) {
s += " "+(Artikel)it.next();
};
}
public int anzahl() { return inhalt.size(); }
public void add (Artikel a) { inhalt.add(a); }
public Warengruppe
(String name, String lagerplatz) {
this.name = name;
this.lagerplatz = lagerplatz;
this.inhalt = new HashSet<Artikel>();
}
private String name;
private String lagerplatz;
private Set<Artikel> inhalt;
class Warengruppe {
Anwendungsbeispiel mit HashSet<E>
58
59
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
}
Es wurde zweifach dasselbe Tisch-Objekt übergeben !
(Gleiches Verhalten bei Strukturgleichheit, s. Warengruppe1.java)
Online:
Online:
Warengruppe1.java Warengruppe2.java
Warengruppe Moebel
Schrank(300) Tisch(200) Stuhl(100)
Systemausgabe bei Referenzgleichheit:
Warengruppe w2 = new Warengruppe("Moebel","L2");
w2.add(tisch);
w2.add(stuhl);
w2.add(schrank);
w2.add(tisch);
System.out.println(w1);
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Wann sind Objekte gleich? (3)
Referenzgleichheit
Online:
Warengruppe0.java
Warengruppe Moebel
Tisch(200) Tisch(200) Schrank(300) Stuhl(100)
Systemausgabe beim Benutzen der Standard-Gleichheit:
public static void main (String[] args) {
Warengruppe w1 = new Warengruppe("Moebel","L1");
w1.add(new Artikel("Tisch",200));
w1.add(new Artikel("Stuhl",100));
w1.add(new Artikel("Schrank",300));
w1.add(new Artikel("Tisch",200));
System.out.println(w1);
}
Wann sind Objekte gleich? (2)
Referenzgleichheit
<<interface>>
Collection<E>
61
+ E first();
+ E last()
<<interface>>
SortedSet<E>
►
►
Modifi kation der konkreten Klasse Warengruppe:
►
Aber Systemreaktion:
Exception in thread "main" java.lang.ClassCastException: Artikel
at java.util.TreeMap<K,V>.compare(TreeMap<K,V>.java, Compiled Code)
in java.util.TreeSet<E>:
public class TreeSet<E> … implements SortedSet<E> … { …
class Warengruppe<E> {
private Set<E> inhalt;
public Warengruppe (…) {
…
this.inhalt = new TreeSet<E>();
} …
}
java.util.TreeSet<E> implementiert ein geordnete Menge mit Hilfe eines
Baumes und benötigt zum Sortieren dessen die Prädikat-Schnittstelle
Comparable<E>
►
Sortierung von Mengen mit TreeSet nutzt
Vergleichbarkeit von Elementen
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
// Zustandsveränderer
+ boolean add (E o);
// Query methods
+ E get(int index);
<<interface>>
Set<E>
java.util.SortedSet<E> (Auszug)
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
60
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
62
63
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Modifikation der Klasse „Artikel“:
►
►
►
in allen Fällen schneller !
–
Enthalten
106,5
177,4
erlaubt Operationen für sortierte Mengen
Stärken von TreeSet:
–
Stärken von HashSet:
Einfügen
36,14
150,6
Iteration
39,39
40,04
Gemessener relativer Aufwand für Operationen auf Mengen:
(aus Eckel, Thinking in Java, 2nd ed., 2000)
Typ
HashSet
TreeSet
►
HashSet oder TreeSet?
Online:
Warengruppe3.java
Warengruppe Moebel
Schrank(300) Stuhl(100) Tisch(200)
Systemausgabe:
class Artikel implements Comparable<Artikel> {
...
public int compareTo (Artikel o) {
return name.compareTo(o.name);
}
}
Artikel muss von Schnittstelle Comparable<Artikel> erben
►
Anwendungsbeispiel mit TreeSet<E>
65
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
64
E
LinkedList<E>
ArrayList<E>
E
<<interface>>
Set<E>
<<interface>>
List<E>
K,V
K,V
TreeMap<K,V>
TreeSet<E>
HashMap<K,V>
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
E
HashSet<E>
E
<<interface>>
SortedSet<E>
E
E
<<interface>>
Collection<E>
E
Collection Framework (Überblick) (Maps)
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.6 Kataloge mit Map
66
67
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
+ preis(): int
1
Artikel
– name: String
– preis: int
*
code: String
Katalog
– name: String
+ put (code: String, a: Artikel)
+ get (code: String): Artikel
+ anzahl(): int
HashMap ist eine sehr günstige
Umsetzung für qualifizierte
Assoziationen:
Der Qualifikator bildet den
Schlüssel; die Zielobjeke den Wert
Hier:
►
Schlüssel: code:String
►
Wert: a:Artikel
►
►
Anwendungsbeispiel: Verfeinerung von
qualifizierten Assoziationen in UML
// Zustandsveränderer
+ void clear();
+ V put (K key, V value);
+ boolean remove (V o);
<<class>>
HashMap<K,V>
Map liefert funktionale Abhängigkeit zwischen Schlüssel und Wert
–
<<interface>>
Map<K,V>
Ein Schlüssel liefert einen Wert (Funktion).
–
Eine Map ist ein „assoziativer Speicher“ (associative array), der Objekte als
Werte (value) unter Schlüsseln (key) zugreifbar macht
// Anfragen (query methods)
+ int size();
+ boolean isEmpty();
+ boolean containsKey(K key);
+ boolean containsValue(V value);
+ V get (K key);
+ int hashCode();
+ Iterator iterator();
+ Set<K> keySet<E>();
+ Set<V> values();
►
java.util.Map<K,V> (Auszug)
68
69
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Ordnung auf den Schlüsseln: SortedMap (Implementierung z.B.TreeMap).
put(...) überschreibt vorhandenen Eintrag (Ergebnis = vorhandener Eintrag).
}
Katalog k = new Katalog("Katalog1"); Systemausgabe:
k.put("M01",tisch);
Katalog Katalog1
k.put("M02",stuhl);
M03 -> Schrank(300)
M02 -> Stuhl(100)
k.put("M03",schrank);
M01 -> Tisch(200)
System.out.println(k);
Katalog Katalog1
k.put("M03",regal);
M03 -> Regal(200)
M02 -> Stuhl(100)
System.out.println(k);
M01 -> Tisch(200)
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Artikel regal = new Artikel("Regal",200);
Testprogramm für Anwendungsbeispiel:
Speicherung der Waren mit Schlüsseln
class
class Katalog
Katalog {{
private
private String
String name;
name;
private
private Map<String,Artikel>
Map<String,Artikel> inhalt;
inhalt; //
// Polymorphe
Polymorphe Map
Map
public
public Katalog
Katalog (String
(String name)
name) {{
this.name
=
name;
this.name = name;
this.inhalt
this.inhalt == new
new HashMap<
HashMap<String,Artikel
String,Artikel>();
>();
}}
public
public void
void put
put (String
(String code,
code, Artikel
Artikel a)
a) {{
inhalt.put(code,a);
inhalt.put(code,a);
}}
public
public int
int anzahl()
anzahl() {{
return
return inhalt.size();
inhalt.size();
}}
public
public Artikel
Artikel get
get (String
(String code)
code) {{
return
return (Artikel)inhalt.get(code);
(Artikel)inhalt.get(code);
}}
...
...
}}
Online:
Katalog.java
Anwendungsbeispiel mit HashMap
70
71
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
■
■
■
key: K
key.hashCode()
hashcode
%
capacity
entry index
value: V
value2: V
key2: K
value1: V
capacity
key1.hashCode()
= key2.hashCode()
0
value?: V
Überlaufliste
Bei nicht eindeutigen Schlüsseln, oder auch durch die Normierung, werden
Einträge doppelt “adressiert” (Kollision)
key1: K
–
Die Hashfunktion ist mehrdeutig (nicht injektiv):
Verfahren zur Kollisionsauflösung:
Überlauflisten (z.B. mit List)
Überlaufbaum (TreeSet)
Überlauf in der Hashtabelle
►
Kollision beim Einstechen
value: V
V
K
hashCode(): int
0
hashtab
Mit dem Eintragswert wird in eine Hashtabelle eingestochen
Der Hashwert wird auf einen Zahlenbereich modulo der Kapazität der Hashtabelle
abgebildet, d.h., der Hashwert wird auf die Hashtabelle “normiert”
Das Objekt liefert seinen Hashwert mit der Hash-Funktion hashCode()
Typischerweise wird der Schlüssel (key) transformiert:
Object
►
Effekt von hashtab.put(key:K,value:V)
Prinzip der Hashtabelle
72
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
73
E
E
E
TreeSet<E>
HashMap<K,V>
HashSet<E>
K,V
Hashtable<K,V> TreeMap<K,V>
K,V
K,V
E
E
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.7 Optimierte Auswahl von
Implementierungen von
Datenstrukturen
Vector<E>
LinkedList<E>
ArrayList<E>
E
<<interface>>
Set<E>
<<interface>>
List<E>
<<interface>>
SortedSet<E>
E
E
<<interface>>
Collection<E>
E
Weitere Implementierungen in der CollectionHierarchie
74
►
►
Effizienz
{unique} {non-unique}
{set} {bag} {sequence}
{union} {subsets}
Eindeutigkeit:
Kollektionsart:
Zusammenhang:
■
■
■
mit Duplikaten
ohne Duplikate
geordnet
ungeordnet
sortiert
unsortiert
Sortierung
mit Schlüssel
ohne Schlüssel
Schlüssel
Anpassung an
vorgefertigte Lösung
Entwicklung
Entwicklungeiner
einer
neuartigen
Lösung
neuartigen Lösung
Effizienz-Verbesserung:
Effizienz-Verbesserung:Ggf.
Ggf.Experimente
Experimentemit
mitLaufzeiten,
Laufzeiten,
Speicherverbrauch,
Energieverbrauch
Speicherverbrauch, Energieverbrauch
Suche nach vorgefertigten Lösungen
(Nutzung der Collection-Bibliothek)
Abstraktion auf die wesentlichen Eigenschaften
Identifikation
Identifikationder
derfunktionalen
funktionalenAnforderungen
Anforderungenan
andie
dieDatenstruktur:
Datenstruktur:
Facetten
der
Funktionalität,
häufig
benutzte
Operationen
(Benutzungsprofil)
Facetten der Funktionalität, häufig benutzte Operationen (Benutzungsprofil)
Vorgehensweise beim funktionalen und
effizienzbasierten Datenstruktur-Entwurf
Duplikate
Ordnung
Beim Übergang zum Implementierungsmodell müssen diese Bedingungen
auf Unterklassen von Collections abgebildet werden
{ordered} {unordered}
Ordnung:
■
An das Ende einer UML-Assoziation können folgende Bedingungen notiert
werden:
Facetten und Assoziationsarten
Funktion
75
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
76
77
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
nein
SortedMap<K,V>
Sortierung relevant?
Elemente "über"/"unter" x
kleinstes/größtes Element
SortedSet<E>
Set<E>
Sortierung der
Schlüssel relevant?
dynamisch erweiterbar
"ist enthalten"-Abfrage für Schlüssel
Abfrage eines Werts für einen Schlüssel
Entfernen eines Schlüssel/Wert-Paars
Einfügen eines Werts für einen Schlüssel
Map<K,V>
inhalt
* {mod}
Artikel (Z)
1) Assoziation anlegen
2) Assoziation entfernen
3) Durchlaufen aller bestehenden
Assoziationen zu Z-Objekten
4) Manchmal: Abfrage, ob
Assoziation zu einem
Z-Objekt besteht
5) Keine Obergrenze der
Multiplizität gegeben
Anforderung
Set<E>
5) Maximalanzahl der Elemente
unbekannt;
dynamisch erweiterbar
4) "ist enthalten"-Abfrage
1) Einfügen (ohne Reihenfolge)
2) Entfernen (ohne Reihenfolge)
3) Aufzählen aller Elemente
Realisierung
Datenstruktur im A-Objekt für Z-Referenzen
Warengruppe (A)
Beispiel: Realisierung von unidirektionalen
Assoziationen
Entfernen an i-ter Position
Ersetzen an i-ter Position
Abfrage an i-ter Position
List<E>
ja
Einfügereihenfolge relevant?
Elemente doppelt?
Collection<E>
Einfügen eines Elements
Entfernen eines Elements
Aufzählen aller Elemente
"ist enthalten"-Abfrage
dynamisch erweiterbar
Suche nach vorgefertigten Lösungen (anhand der
Facetten der Collection-Klassen)
78
79
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
* {unique}
inhalt
Artikel (Z)
Artikel (Z)
}
public A {
assoc = new TreeSet<Z>();
}
public boolean testAssoc (Z ziel) {
return assoc.contains(ziel);
}
class A {
private Set<Z> assoc;
...
public void addAssoc (Z ziel) {
assoc.add(ziel);
}
Warengruppe (A)
* {unique,
sorted}
inhalt
Realisierung von sortierten Assoziationen mit
Set<E>
}
public A {
assoc = new HashSet<Z>();
}
public boolean testAssoc (Z ziel) {
return assoc.contains(ziel);
}
class A {
private Set<Z> assoc;
...
public void addAssoc (Z ziel) {
assoc.add(ziel);
}
Warengruppe (A)
Realisierung von ungeordneten Assoziationen mit
Set<E>
►
►
►
80
81
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
►
►
►
►
►
Testfälle
Testfälle
Objektimplementierung
Objektimplementierung
Netzimplementierung
Netzimplementierung
Testfälle
Feinentwurf
Feinentwurf
Verfeinerung von Assoziationen
Grobentwurf
Grobentwurf
Testfälle
Zusicherungen
Zusicherungen
Methodentest
Methodentest
Klassentest
Klassentest
Netztest
Netztest
Integrationstest
Komponententest
Systemtest
Abnahmetest
Weniger Casts, mehr Typsicherheit
■
Die Java Collection Library bietet geordnete, ungeordnete Collections sowie
Kataloge
Element-Typ verfeinert Object
■
Static vs. dynamic vs. no typing
Safe Application Development (SAD) nur mit statischen Typisierung möglich
Rapid Application Development (RAD) benötigt dynamische Typisierung
Generische Collections besitzen den Element-Typ als Typ-Parameter
Was haben wir gelernt
Zum Schluss der
Akzeptanztest (Abnahmetest)
Dann der beta-Test


Dann das System
Dann das Netz testen
Dann die Komponente
Dann die einzelne Klasse testen
Verträge und Testfälle für das Netz
entwerfen
Analyse
Zuerst Verträge und Testfälle für die
Klasse bilden
Analyse






Netze werden im Grob- und
Feinentwurf in UML modelliert
In der Phase “Netzimplementierung” in
Java umgesetzt
Die Tests werden bottom-up erledigt:
Ziel: V-Modell mit Standard-Testprozess
mit Netz-Entwurf und -Test
82
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
83
►
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Appendix A
Generische Command Objekte
Diese Folien bauen auf der Vorlesung Softwaretechnologie auf von © Prof.
H. Hussmann, 2002. Used by permission.
The End
84
85
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
.. ist ab Java 1.5 ohne Probleme nebeneinander möglich
funktioniert
for (int jahr = 0; jahr < archiv.size(); jahr++) {
for (int jahr = 0; jahr < archiv.size(); jahr++) {
listOfRechnung = archiv.get(jahr);
listOfRechnung = archiv.get(jahr);
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
}
}
archiv.add(listOfRechnung);
archiv.add(listOfRechnung);
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
archiv.get(0).add(rechnung);
archiv.get(0).add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
archiv.get(0).add(best);
archiv.get(0).add(best);
Übersetzt auch,
aber Laufzeitfehler
beim Cast...
// Das Archiv fasst alle Rechnungen aller bisherigen Jahrgänge zusammen
// Das Archiv fasst alle Rechnungen aller bisherigen Jahrgänge zusammen
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>();
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>();
// listOfRechnung fasst die Rechnungen des aktuellen Jahres zusammen
// listOfRechnung fasst die Rechnungen des aktuellen Jahres zusammen
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
►
Benutzung von getypten und ungetypten
Schnittstellen
// Das Archiv listOfRechnung fasst die Rechnungen des
// Das Archiv listOfRechnung fasst die Rechnungen des
// aktuellen Jahres zusammen
// aktuellen Jahres zusammen
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>;
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>;
archiv.add(listOfRechnung);
archiv.add(listOfRechnung);
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
funktioniert
archiv.get(0).add(rechnung);
archiv.get(0).add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
archiv.get(0).add(best);
Übersetzungsarchiv.get(0).add(best);
Fehler
for (int jahr = 0; jahr < archiv.size(); jahr++) {
for (int jahr = 0; jahr < archiv.size(); jahr++) {
listOfRechnung = archiv.get(jahr);
listOfRechnung = archiv.get(jahr);
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = listOfRechnung.get(i);
rechnung = listOfRechnung.get(i);
}
}
}
}
Generizität auf Containern
funktioniert auch geschachtelt
86
87
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
z.B. sind alle Instanzen mit unboxed objects als boxed objects realisiert
–
}
T attribute<T>
Templateparameter können Variablen umbenennen
C++ bietet Code-Templates (snippets, fragments) an, mit denen man mehr
parameterisieren kann, z.B. Methoden
In C++ können Templateparameter Variablen umbenennen:
template class C <class T> {
Verliert etwas Effizienz, da der Übersetzer alle Typinformation im generierten
Code vergisst und nicht ausnutzt
–
In Java: einmalige Übersetzung des generischen Datentyps
►
►
Es gibt eine Standard-Funktion in der Klasse des Funktionalobjektes, das die
Berechnung ausführt (Standard-Name, z.B. execute() oder doIt())
// A functional object that is like a constant
// A functional object that is like a constant
interface NullaryOpCommand { void execute();
interface NullaryOpCommand { void execute();
void undo(); }
void undo(); }
// A functional object that takes one parameter
// A functional object that takes one parameter
interface UnaryOpCommand<P> { P execute(P p1);
interface UnaryOpCommand<P> { P execute(P p1);
void undo(); }
void undo(); }
// A functional object that operates on two parameters
// A functional object that operates on two parameters
interface BinOp<P> { P execute(P p1, P p2);
interface BinOp<P> { P execute(P p1, P p2);
void undo(); }
void undo(); }
Zur Laufzeit kann man das Funktionalobjekt mit Parametern
versehen, herumreichen, und zum Schluss ausführen
–
Funktionalobjekte können Berechnungen kapseln und später
ausführen (laziness) (Entwurfsmuster Command)
Ein Funktionalobjekt (Kommandoobjekt) ist ein Objekt, das eine Funktion
Ein Funktionalobjekt (Kommandoobjekt) ist ein Objekt, das eine Funktion
darstellt (reifiziert).
darstellt (reifiziert).
Implementierungsmuster Command:
Generische Methoden als Funktionale Objekte
►
►
►
Unterschiede zu C++
88
89
// An interface for a collection of binary operation on
// An interface for a collection of binary operation on
// collections
// collections
interface Functional<Collection<P>,B extends BinOp<P>> {
interface Functional<Collection<P>,B extends BinOp<P>> {
P compute(Collection<P> p);
P compute(Collection<P> p);
}
}
class Accumulate<C,E> implements Functional<C,BinOp<E>> {
class Accumulate<C,E> implements Functional<C,BinOp<E>> {
E curSum;
E element;
BinOp<E> binaryOperation;
E curSum;
E element;
BinOp<E> binaryOperation;
public E compute(C coll) {
public E compute(C coll) {
for (int i = 0; i < coll.size(); i++) {
for (int i = 0; i < coll.size(); i++) {
element = coll.get(i);
element = coll.get(i);
curSum = binaryOperation.execute(curSum,element);
curSum = binaryOperation.execute(curSum,element);
}
}
return curSum;
return curSum;
}
}
}
}
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Appendix B
Bestimmung von konkreten
Datentypen
C,E
Accumulate
Functional
B
P
Anwendung: Akkumulatoren und andere generische Listenoperationen
BinOp
►
Generische Methoden als Funktionale Objekte
Collection
<P>
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
90
91
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
raumFestlegen()
einladen()
absagen()
verschieben()
*
Teambesprechung
titel
beginn
dauer
anzahl
*
*
leitet
für
1
2..*
Teilnahme
0..1 Ort
1 Leiter
10..*
►
►
►
» SortedSet<Besprechungsraum> (Elemente: Besprechungsraum)
Datenstruktur für vorhandene Räume in Klasse Raumverwaltung
Datenstruktur in Klasse Besprechungsraum für Zeiten (Stunden):
–
–
TerminvTreeSet.java
» Map<Hour,Teambesprechung> (Schlüssel: Hour, Wert:
Teambesprechung)
Online:
Datenstruktur in Klasse Besprechungsraum:
Zusatzanforderung (Variante): Überprüfung, welcher andere Termin eine
bestimmte Stunde belegt.
» Set<Hour> (Elemente: Hour)
Operation in Klasse Besprechungsraum:
boolean frei (Hour beginn, int dauer)
–
Überprüfung eines Raumes, ob er für die Zeit ab beginn für die Länge
dauer bereits belegt ist.
–
Suche unter vorhandenen Räumen nach Raum mit mindestens der
Kapazität groesse, aber möglichst klein.
static Besprechungsraum freienRaumSuchen
(int groesse, Hour beginn, int dauer)
1
Teammitglied
name
abteilung
terminBestätigen()
0..1
1
name
Team
Beispiel 2: Sortierte Liste von Räumen in der
Raumverwaltung
*
Privater
Termin
beschreibg
beginn
dauer
ort
wegzeit
genehmigen()
verschieben()
Termin
reservieren()
freigeben()
freienRaumSuchen()
Besprechungsraum
raumNr
kapazität
Beispiel 2: Analysemodell der Terminverwaltung
92
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
}
1
1) Verfeinerung von
Assoziationen
2) Generische Container
3) Polymorphe Container
4) Weitere Arten von Klassen
5) Ungeordnete Collections
6) Kataloge
7) Optimierte Auswahl von
Implementierungen für
Datenstrukturen
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Version 14-0.4, 03.05.14
TU Dresden
Fakultät für Informatik
Lehrstuhl Softwaretechnologie
Institut für Software- und
Multimediatechnik
Prof. Dr. rer. nat. Uwe Aßmann
21) Verfeinern von UML-Assoziationen mit
dem Java-2 Collection Framework
// Suche freien Raum aufsteigend nach Größe
static Besprechungsraum freienRaumSuchen
(int groesse, Hour beginn, int dauer) {
Besprechungsraum r = null;
boolean gefunden = false;
Iterator it = vorhandeneRaeume.iterator();
while (! gefunden && it.hasNext()) {
r = (Besprechungsraum)it.next();
if (r.grossGenug(groesse)&& r.frei(beginn,dauer))
gefunden = true;
};
if (gefunden) return r;
else
return null;
} ...
class Raumverwaltung {
// Vorhandene Raeume, aufsteigend nach Größe sortiert
// statisches Klassenattribut und -methode
private static SortedSet<E> vorhandeneRaeume
= new TreeSet<Besprechungsraum>();
Raumverwaltung: Freien Raum suchen
2
3
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
http://www.oracle.com/technetwork/java/javase/documentation/index.html
►
►
►
►
http://download.oracle.com/javase/6/docs/
Tutorials http://download.oracle.com/javase/tutorial/
Generics Tutorial:
http://download.oracle.com/javase/tutorial/extra/generics/index.html
■
Im Wesentlichen sind die Dokumentationen aller Versionen von Java 6 an
nutzbar:
Empfohlene Literatur
JDK Tutorial für J2SE oder J2EE, Abteilung Collections
►
Obligatorische Literatur
5
4
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Beispiel “Kataloge mit Maps”
Katalog-Mit-Abbildung/Katalog.java
Katalog-Mit-Abbildung/Katalog2.java
Beispiel “Warengruppen mit Mengen”
Warengruppe-Mengen/Warengruppe0.java
..
Warengruppe-Mengen/Warengruppe4.java
Beispiel "Bestellung mit Listen":
Bestellung-Collections/Bestellung0.java
..
Bestellung-Collections/Bestellung4.java
Über die Homepage der Lehrveranstaltung finden Sie verschiedene JavaDateien dieser Vorlesung.
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.1 Verfeinern von
Assoziationen
►
►
►
►
Hinweis: Online-Ressourcen
Input
6
7
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
TestTestTreiber
Treiber
Test-Umgebung
Eingabedaten
Programm
Programm
(SUT)
(SUT)
►
►
►
►
Ok
Error
Strange-null-pointer-exception-The-Official-Microsoft-ASP.pdf
Bitte mal nach “strange null pointer exception” suchen:
https://forums.oracle.com/forums/thread.jspa?threadID=2056540
http://stackoverflow.com/questions/8089798/strange-java-string-array-nullpointer-exception
Schon mal 3 Tage nach einem Zeiger-Fehler (pointer error) gesucht?
Ausgabe-Netz
(Ist)
NetzNetzKomparator
Komparator
Ausgabe-Netz (Soll)
Solange
Solangeein
einProgramm
Programmkeine
keineTests
Testshat,
hat,ist
istes
eskeine
keineSoftware
Software
Testen beinhaltet die Ist-Soll-Analyse für Objektnetze
Stimmt mein Netz mit meinem Entwurf überein?
Warum ist das wichtig?
►
►
Objektorientierte Software hat eine testgetriebene Architektur für Objektnetze
8
*
*
+ preis(): int
1
+ preis(): int
für
Artikel
– name: String
– preis: int
1
Artikel
– name: String
– preis: int
für
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
1
Bestellposition
– anzahl: String
– preis: int
1
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
*
1 {ordered}
<<interface>>
Array
Online:
Bestellung0.java
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Modell einer Bestellungsabwicklung, eines einfachen Objektnetzes (Hierarchie):
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
►
Verfeinern von Assoziationen (Netzverfeinerung)
9
}
Bestellung0.java
public void
void sonderpreis (int pos,
pos, int
int preis) {
liste[pos].einzelpreis(preis);
}
public int
int auftragssumme() {
int s = 0;
for(int i=0; i<anzahl; i++) s +=
+= liste[i].positionspreis();
liste[i].positionspreis();
return s;
}
Online:
public
public Bestellung(String kunde) {{
this.kunde = kunde;
kunde;
liste = new Bestellposition[20];
}}
public
public void
void neuePosition
neuePosition (Bestellposition
(Bestellposition b) {
liste[anzahl]
liste[anzahl] == b;
b;
anzahl++;
// was passiert
passiert bei
bei mehr als
als 20
20 Positionen ?
}}
public
public void loeschePosition (int pos)
pos) {{
// geht mit Arrays nicht einfach
einfach zu realisieren !
}}
private
private String
String kunde;
kunde;
private
private Bestellposition[] liste;
private
private int anzahl = 0;
class Bestellung {
Einfache Realisierung mit Arrays –
Was ist problematisch?
•Einfache Antwort 1: durch Abbildung auf Java Arrays
•Zentrale Frage: Wie bilde ich einseitige Assoziationen aus UML auf Java ab?
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
11
Bestellung("TUD");
Bestellposition(tisch,1));
Bestellposition(stuhl,4));
Bestellposition(schrank,2));
Bestellung
Bestellungfuer
fuerKunde
KundeTUD
TUD
0.0.11xxTisch
TischEinzelpreis:
Einzelpreis:200
200Summe:
Summe:200
200
1.1.44xxStuhl
StuhlEinzelpreis:
Einzelpreis:50
50Summe:
Summe:200
200
2.2.22xxSchrank
Einzelpreis:
300
Summe:
Schrank Einzelpreis: 300 Summe:600
600
Auftragssumme:
Auftragssumme:1000
1000
public static void main (String[] args) {
...
b1.sonderpreis(1,50);
b1.print();
}
Testprogramm für Anwendungsbeispiel (2)
Bestellung fuer Kunde TUD
0. 1 x Tisch Einzelpreis: 200 Summe: 200
1. 4 x Stuhl Einzelpreis: 100 Summe: 400
2. 2 x Schrank Einzelpreis: 300 Summe: 600
Auftragssumme: 1200
Bestellung b1 = new
b1.neuePosition(new
b1.neuePosition(new
b1.neuePosition(new
b1.print(); ...}
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Testprogramm für Anwendungsbeispiel (1)
Online:
Bestellung0.java
10
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
12
13
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Fest zur Allokationszeit
–
Automatisches Verschieben bei Löschen und Mitten-Einfügen
–
►
►
Verwendung von Vererbung zur Strukturierung
Flexibel auch zur eigenen Erweiterung
–
–
Antwort: Einziehen von Behälterklassen (collections) aus dem CollectionFramework
Flachklopfen (lowering) von Sprachkonstrukten: Wir klopfen Assoziationen zu
Java-Behälterklassen flach.
–
–
Zentrale Frage: Wie bilde ich einseitige Assoziationen aus UML flexibel
auf Java ab?
Meiste Standard-Datenstrukturen abgedeckt
–
Probleme werden durch das Java-Collection-Framework gelöst, eine
objektorientierte Datenstrukturbibliothek für Java
Collections
Antwort 2: durch Abbildung auf die Schnittstelle Collection
►
Viele Algorithmen laufen auf sortierten Universen wesentlich schneller als auf
unsortierten (z.B. Anfragen in Datenbanken)
Wie bilde ich einseitige Assoziationen aus UML auf Java ab?
–
Was passiert, wenn keine Ordnung benötigt wird?
Kann das Array sortiert werden?
http://en.wikipedia.org/wiki/Dynamic_array
–
Dynamische Arrays sind dynamisch erweiterbar:
Fest zur Übersetzungszeit
–
Java Arrays besitzen eine feste Obergrenze für die Zahl der enthaltenen
Elemente
►
►
►
►
►
Probleme der Realisierung von Assoziationen mit
Arrays
14
15
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
*
*
1 {ordered}
<<interface>>
Collection
}
Online:
Bestellung2LinkedList.java
public Bestellung(String kunde) {
this.kunde
this.kunde = kunde;
liste
liste == new
new LinkedList<Bestellposition>();
LinkedList<Bestellposition>(); // Erklärung
Erklärung später
später
}
public void neuePosition (Bestellposition b)
b) {{
liste.set(anzahl,b);
anzahl++;
//
anzahl++;
// was passiert
passiert jetzt bei mehr als
als 20
20 Positionen ?
}
public void loeschePosition (int pos)
pos) {
liste.remove(pos);
}
public void sonderpreis (int pos, int
int preis)
preis) {{
liste.get(pos).einzelpreis(preis);
liste.get(pos).einzelpreis(preis);
}
public int auftragssumme() {
int
int s = 0;
for(int
for(int i=0;
i=0; i<anzahl;
i<anzahl; i++) ss += liste.get(i).positionspreis();
liste.get(i).positionspreis();
return
return s;
s;
}
class Bestellung {
private String kunde;
private List<Bestellposition> liste;
private int anzahl = 0;
Einfache Realisierung mit Collection-Klasse “List”
+ preis(): int
+ preis(): int
1
Artikel
– name: String
– preis: int
für
Artikel
– name: String
– preis: int
1
*
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
für
Bestellposition
– anzahl: String
– preis: int
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Ersetzen von “*”-Assoziationen durch Behälterklassen
Bsp.: Verfeinern von bidir. Assoziationen durch
Behälterklassen
16
►
►
Hilfsmittel:
●
Typisierung weglassen
●
Ev. dynamische Typisierung, damit Fehler
zur Laufzeit identifiziert werden können
●
Mächtige Operationen einer Skriptsprache
–
17
Java
1.6
Mehr Entwurfswissen aus dem Entwurf in die Implementierung übertragen
Hilfsmittel:
●
Statische Typisierung, damit der Übersetzer viele Fehler entdeckt
●
Generische Klassen
Aus der Definition einer Datenstruktur können Bedingungen für ihre Anwendung
abgeleitet werden
Generische Collections für typsicheres Aufbauen von Objektnetzen (Java)
–
–
–
–
Zuverlässigkeit
Java
groovy
Guten, stabilen, wartbaren Code schreiben
Zeit
–
Safe Application Development (SAD)
Schneller viel Code schreiben
–
Rapid Application Development (RAD)
Orthogonale Trends in der Softwareentwicklung


Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Generische Behälterklassen
Collection<Object>
21.2 Die Collection-Bibliothek
•Gradual Typing für beides
– Typen werden Schritt für Schritt annotiert
– http://ecee.colorado.edu/~siek/gradual-obj.pdf
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
18
19
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Lieferschein
List<Bestellung>
List<Lieferschein>
List<Formular>
Bsp.: Hierarchie von Listen
Bestellung
Formular
Bsp.: Elemente einer Hierarchie
List<Rechnung>
Rechnung
21
20
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
mit Duplikaten
ohne Duplikate
Sortierung
sortiert
unsortiert
<<interface>>
SortedSet
Sortierung
<<interface>>
Set
Duplikate
Schlüssel
Schlüssel
<<interface>>
SortedMap
<<interface>>
Map
mit Schlüssel
ohne Schlüssel
/home/ua1/Courses/ST1/Material/jdk-docs/index.html
<<interface>>
List
Ordnung
<<interface>>
Collection
Java Collection Framework:
Prinzipielle Struktur
Duplikate
Facetten sind orthogonale Dimensionen einer Klassifikation oder eines
Modells
geordnet
ungeordnet
–
Behälterklassen können anhand von verschiedenen Facetten klassifiziert
werden
Ordnung
►
Facetten von Behälterklassen (Collections)
•Collection (Behälter, Kollektion):
– Ansammlung von Datenelementen
– Hinzufügen, Entfernen, Suchen, Durchlaufen
•Set (Menge):
– Reihenfolge des Einfügens, Mehrfachvorkommen spielen keine
Rolle
– SortedSet (geordnete Menge): Ordnung auf den Elementen +
Sortierung
•List (Liste):
– Mehrfachvorkommen werden separat abgelegt
– Reihenfolge des Einfügens bleibt erhalten
•Map (Abbildung, mapping, associative array ):
– Zuordnung von Schlüsselwerten auf Eintragswerte
– Menge von Tupeln: Mehrfachvorkommen bei Schlüsseln verboten,
bei Einträgen erlaubt
– SortedMap (geordnete Abbildung): Ordnung auf den Schlüsseln +
Sortierung danach
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
TreeMap
23
Programmierfehler!
Laufzeitfehler!!
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
listOfRechnung.add(best);
listOfRechnung.add(best);
Bei der Konstruktion von Collections werden oft Fehler programmiert, die bei
der Dekonstruktion zu Laufzeitfehlern führen
Kann in Java < 1.5 nicht durch den Übersetzer entdeckt werden
Klassische Behälterklassen arbeiten auf “Object”, können also nicht näher
qualifizieren, was sie beinhalten. Das führt leicht zu Fehlern.
Behälterklassen müssen das genau qualifizieren, was sie beinhalten.
►
►
Problem 1 ungetypter Schnittstellen: Laufzeitfehler
Die Java-Collection-Hierarchie ist in zwei Ebenen eingeteilt: Oben liegen
Schnittstellen, unten konkrete Implementierungsklassen.
Im Wesentlichen werden drei Kategorien unterschieden: geordnete
Listen, ungeordnete Mengen und Kataloge (Maps)
TreeSet
HashMap
<<interface>>
SortedMap
<<interface>>
Map
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet
<<interface>>
Set
HashSet
Implementierungsklassenschicht
LinkedList
ArrayList
<<interface>>
List
<<interface>>
Collection
Schnittstellen und Implementierungen im unsicheren,
ungetypten Collection-Framework (vor Java 1.5)
Schnittstellenschicht
22
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
24
ArrayList
add(Object o)
get(pos: int): Object
...
Zusicherung:
Zusicherung:Alle
Allevom
vomObjekt
Objekterreichbaren
erreichbarenObjekte
Objekte
sind
sindaus
ausder
derKlasse
KlasseRechnung.
Rechnung.
listOfRechung:List
*
Cast nötig, obwohl
alles Rechnungen
Rechnung
*
Object
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
Diesmal ok
Bei der Dekonstruktion von Collections müssen unnötig Typumwandlungen
(Casts) spezifiziert werden
Typisierte Collections erhöhen die Lesbarkeit, da sie mehr Information geben
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Rechnung rechnung2 = new Rechnung();
Rechnung rechnung2 = new Rechnung();
listOfRechnung.add(rechnung2);
listOfRechnung.add(rechnung2);
►
►
Problem 2 ungetypter Schnittstellen: Unnötige
Casts
25
In UML
E
Collection<E>
content
E
–
Sprachregelung: “Collection of E”
In Java
}
E content[];
class Collection<E> {
►
Auch Collection-Klassen können mit einem Typparameter versehen
werden.
Collection
►
Eine generische Behälterklasse ist eine Klassenschablone einer
Eine generische Behälterklasse ist eine Klassenschablone einer
Behälterklasse, die mit einem Typparameter für den Typ der
Behälterklasse, die mit einem Typparameter für den Typ der
Elemente versehen ist.
Elemente versehen ist.
Generische Behälterklassen
Wenn man aus einer ungetypten Behälterklasse ein Element herausholt,
muss es von “Object” auf einen spezielleren Typ gewandelt (gecastet)
werden.
Das führt zu “Codeverschmutzung”, d.h. unübersichtlichem Code.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
26
►
List
–
E
SortedSet
Set
Collection
E
E
E
E: Element, K: Key, V: Value
Blocking
Queue
Queue
E
E
K,V
K,V
SortedMap
Map
Die generische Schnittstellen-Hierarchie der Collections (seit Java 1.5)
Collection-Hierarchie mit generischen
Schnittstellen
TreeMap<K,V>
HashMap<K,V>
Diese Ansicht zeigt beide Ebenen, generische Schnittstellen und
Implementierungsklassen
TreeSet<E>
HashSet<E>
Implementierungsklassenschicht
LinkedList<E>
ArrayList<E>
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet<E>
<<interface>>
Set<E>
<<interface>>
Collection<E>
<<interface>>
List<E>
Schnittstellenschicht
27
Schnittstellen und Implementierungen im CollectionFramework bilden generische Behälterklassen
Neben den hier betrachteten List, Set, Map gibt es weitere
Unterschnittstellen von Collection, z.B. Queue. Eine “Schlange” ist ein
zirkuläre Liste von Elementen.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
28
E
Blocking
Queue
<Formular>
SortedSet
<Formular>
SortedMap
<Nr,Formular>
Map
<Nr,Formular>
E
E
E
►
E
E
K,V
K,V
SortedMap
Map
Darf man Rechnungen,
Bestellungen und
Lieferscheine in diese
Collections stecken?
Ja.
Blocking
Queue
Queue
29
Bei der Konstruktion von Collections werden jetzt Äpfel von Birnen
unterschieden
Casts sind nicht nötig, der Übersetzer kennt den feineren Typ
Das ist Safe Application Development (SAD)
Mit generischen Behälterklassen können jetzt die Elemente unterschieden
werden, und es braucht keine “Casts”.
Kein Cast mehr nötig
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = listOfRechnung.get(i);
rechnung = listOfRechnung.get(i);
}
}
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
listOfRechnung.add(rechnung);
listOfRechnung.add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
Compilerfehler
listOfRechnung.add(best);
listOfRechnung.add(best);
►
►
►
SAD löst Probleme
Man kann die Hierarchie von generischen Behälterklassen insgesamt auf
einen konkreten Typ instanziieren.
Queue
<Formular>
Set
SortedSet
<<instantiates>>
Set
<Formular>
Collection
<Formular>
List
Collection
Instanziierung der generischen Hierarchie
List
<Formular>
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
31
}
…
public void clear();
public boolean remove (E o);
// Nicht-Monotone Zustandsveränderer
public boolean add (E o);
// Monotone Zustandserweiterer
// Zustandsveränderer
public E[] toArray();
// Repräsentations-Transformierer
public Iterator iterator();
public int hashCode();
public int size();
public boolean equals(E o);
public boolean contains (E o);
public boolean isEmpty();
// Anfragen (Queries)
public interface Collection<E> {
// Zustandsveränderer
+ boolean remove (E o);
+ void clear();
// Monotone Zustandsveränderer
+ boolean add (E o);
// Repräsentations-Trans// formierer
+ E[] toArray();
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
<<interface>>
Collection<E>
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Schnittstelle
java.util.Collection (Auszug)
30
21.2.2 Schnittstellen im Detail
An Behälterklassen sieht man schön, welche Arten von Methoden es gibt
(siehe Kapitel “Klassen”).
Man sieht hier: Query-Methoden, Repräsentationswechsler, monotone und
nicht-monotone Zustandsveränderer,
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
32
}
...
public int indexOf (E o);
public E remove (int index);
public E set (int index, E element);
public E get (int index);
public void clear();
public boolean remove (E o);
public boolean add (E o);
public int size();
public boolean contains (E o);
public boolean isEmpty();
public interface List extends Collection {
// Zustandsveränderer
+ E remove (int index,E o);
+ E set (int index, E o);
+ int indexOf (E o);
// Query methods
+ E get(int index);
<<interface>>
List
<<interface>>
Collection
Unterschnittstelle java.util.List (Auszug)
33
Spezifische Schnittstellen sowie
konkrete Implementierungen in der
Collection-Hierarchie können
spezialisiertes Verhalten aufweisen.
Bsp.: Was ändert sich bei Set im
Vergleich zu List in der Semantik
von add()?
// Zustandsveränderer
+ boolean add (E o);
<<interface>>
Set
<<interface>>
Collection
Set besitzt zur Schnittstelle List eine unterschiedliche Semantik von
“add()”, denn Mengen dürfen Elemente nur einmal enthalten (Duplikate
werden eliminiert).
►
►
Unterschnittstelle java.util.Set (Auszug)
Listen erlauben es, per Index auf die Elemen te der Collection zuzugreifen.
Entsprechend werden alle Kategorien von Methoden mit neuen Methoden
erweitert, die Zugriff per Index ermöglichen.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
35
36
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
*
1 {ordered}
*
<<interface>>
List<Bestellposition>
}
Bestellung2LinkedList.java
public Bestellung(String kunde) {
this.kunde
this.kunde = kunde;
liste
liste == new
new LinkedList<Bestellposition>();
LinkedList<Bestellposition>();
//
// Konkrete Implementierungsklasse
Implementierungsklasse
}
public void neuePosition (Bestellposition b)
b) {{
liste.set(anzahl,b);
anzahl++;
//
anzahl++;
// was passiert
passiert jetzt bei mehr als
als 20
20 Positionen ?
}
public void loeschePosition (int pos)
pos) {
liste.remove(pos);
}
public void sonderpreis (int pos, int
int preis)
preis) {{
liste.get(pos).einzelpreis(preis);
liste.get(pos).einzelpreis(preis);
}
public int auftragssumme() {
int
int s = 0;
for(int
for(int i=0;
i=0; i<anzahl;
i<anzahl; i++) ss += liste.get(i).positionspreis();
liste.get(i).positionspreis();
return
return s;
s;
Online:
}
class Bestellung {
private String kunde;
private List<Bestellposition> liste;
private int anzahl = 0;
Wdh. Einfache Realisierung mit Collection-Klasse
“List”
+ preis(): int
+ preis(): int
1
Artikel
– name: String
– preis: int
für
Artikel
– name: String
– preis: int
1
*
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
+ einzelpreis(): int
+ einzelpreis(p: int)
+ positionspreis(): int
für
Bestellposition
– anzahl: String
– preis: int
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
*
Bestellposition
– anzahl: String
– preis: int
{ordered}
1
Bestellung
– kunde: String
+ neuePosition(b: Bestellposition)
+ löschePosition(pos int)
+sonderpreis(pos: int, preis: int)
+ auftragssumme(): int
+ print()
Ersetzen von “*”-Assoziationen durch Behälterklassen
Verfeinern von bidir. Assoziationen durch
getypte Behälterklassen
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Siedersleben/Denert,
Siedersleben/Denert,
Wie
Wiebaut
bautman
manInformationssysteme,
Informationssysteme,
Informatik-Spektrum
Informatik-Spektrum, ,August
August2000
2000
"Der
"DerAufrufer
Aufruferprogrammiert
programmiertgegen
gegendie
die
Schnittstelle,
Schnittstelle,
er
erbefindet
befindetsich
sichsozusagen
sozusagenim
imluftleeren
luftleerenRaum."
Raum."
TreeSet<E>
TreeMap<K,V>
HashMap<K,V>
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
Implementierung (implements)
Vererbung (extends)
<<interface>>
SortedSet<E>
<<interface>>
Set<E>
HashSet<E>
Implementierungsklassenschicht
LinkedList<E>
ArrayList<E>
<<interface>>
List<E>
<<interface>>
Collection<E>
Schnittstellen und Implementierungen im CollectionFramework bilden generische Behälterklassen
37
21.3 Programmieren gegen Schnittstellen
von polymorphen Containern
Schnittstellenschicht
38
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
39
40
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Operationen
Verhalten der Operationen
Algebraische Spezifikationen
●
Axiomensysteme
Abstrakte Klassen
Interfaces
–
List
Beispiel:
–
–
Praxis:
–
Theorie:
–
–
Abstraktion:
►
►
►
►
Instantiierbare Klassen
Ausführbare Operationen
Komplexität
–
Alternativen
Liste durch Feld (ArrayList)
–
+ ArrayList<E>(int initialCapacity);
+ void ensureCapacity
(int minCapacity);
ArrayList<E>
LinkedList<E>
+ LinkedList<E>();
+ addFirst(E o)
+ addLast(E o)
public class ArrayList<E> implements List<E> {
public ArrayList<E> (int initialCapacity);
public void ensureCapacity (int minCapacity);
...
}
public class LinkedList<E> implements List<E> {
public void addFirst (E o);
public void addLast (E o);
...
}
<<interface>>
List<E>
Verkettete Liste (LinkedList)
–
Beispiel:
–
Praxis:
Datenstrukturen
–
Theorie:
–
–
Konkretisierung:
Konkreter Datentyp
(Implementierung)
Beispiel: Implementierungsklassen
java.util.ArrayList, LinkedList
►
►
►
►
Abstrakter Datentyp
(Schnittstelle)
Polymorphie – zwischen abstrakten und
konkreten Datentypen
Polymorphe Containerklassen erlauben das Programmieren gegen
Schnittstellen der gemeinsamen Oberklasse.
Polymorphe generische Containerklassen sind zusätzlich typsicher, was
die Verwendung von Elementen betrifft.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
41
public Bestellung(String kunde) {
this.kunde = kunde;
this.liste = new LinkedList<
Bestellposition> ();
} ...
Bei polymorphen Containern muß der Code bei Wechsel der
Datenstruktur nur an einer Stelle im Konstruktor geändert werden!
public Bestellung(String kunde) {
this.kunde = kunde;
this.liste = new ArrayList<
Bestellposition> ();
} ...
!
List<Bestellposition>
ist ein Interface,
keine Klasse !
class
class Bestellung
Bestellung {{
private
private String
String kunde;
kunde;
private
private List<Bestellposition>
List<Bestellposition> liste;
liste;
...
//
Konstruktor
... // Konstruktor s.
s. u.
u.
public
void
neuePosition
(Bestellposition
public void neuePosition (Bestellposition b)
b) {{
liste.add(b);
}}
liste.add(b);
public
public void
void loeschePosition
loeschePosition (int
(int pos)
pos) {{
liste.remove(pos);
}}
liste.remove(pos);
public
public void
void sonderpreis
sonderpreis (int
(int pos,
pos, int
int preis)
preis) {{
liste.get(pos).einzelpreis(preis);
}}
liste.get(pos).einzelpreis(preis);
-- Polymorphe Container
Programmieren gegen Schnittstellen
42
Iteration
3850
12200
9110
16250
Einfügen
-500
110
550
Entfernen
-46850
60
46850
•Gemessener relativer Aufwand für Operationen auf Listen:(aus Eckel,
Thinking in Java, 2nd ed., 2000)
– Stärken von ArrayList: wahlfreier Zugriff
– Stärken von LinkedList: Iteration, Einfügen und Entfernen
irgendwo in der Liste
– Vector (deprecated) ist generell die langsamste Lösung
– Optimierung von inneren Schleifen durch Auswahl von
Implementierungen mit geeignetem Zugriffsprofil
•Innere Schleifen bilden die „heißen Punkte“ (hot spots) eines Programms
Lesen
1430
3070
16320
4890
Gemessener relativer Aufwand für Operationen auf Listen:
(aus Eckel, Thinking in Java, 2nd ed., 2000)
Innere Schleifen bilden die „heißen Punkte“ (hot spots) eines Programms
Typ
array
ArrayList
LinkedList
Vector
►
►
Aus
Ausalternativen
alternativenImplementierungen
Implementierungeneiner
einerSchnittstelle
Schnittstellewählt
wähltman
mandiejenige,
diejenige,die
diefür
für
das
dasBenutzungsprofil
Benutzungsprofilder
derOperationen
Operationendie
diegrößte
größteEffizienz
Effizienzbereitstellt
bereitstellt
(Geschwindigkeit,
Speicherverbrauch,
Energieverbrauch)
(Geschwindigkeit, Speicherverbrauch, Energieverbrauch)
Welche Listen-Implementierung soll man
wählen?
Bei diesem Beispiel von generischen Behälterklassen sieht man
•die Typdefinition erlaubt die polymorphe Verwendung
•die Allokationen in den Konstruktoren der konkreten
Implementierungsklassen geben die spezifische
Implementierungsmethode an
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
44
+ ArrayList<E>(int initialCapacity);
// Management-Methode
+ void ensureCapacity
(int minCapacity);
ArrayList<E>
LinkedList<E>
+ LinkedList<E>();
+ addFirst(E o)
+ addLast(E o)
public class ArrayList<E> implements List<E> {
public ArrayList<E> (int initialCapacity);
// Management-Methode (Optimierer-Methode)
public void ensureCapacity (int minCapacity);
...
}
public class LinkedList<E> implements List<E> {
public void addFirst (E o);
public void addLast (E o);
...
}
<<interface>>
List<E>
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
Management-Methoden in
java.util.ArrayList, LinkedList
43
21.4) Weitere Arten von Klassen und
Methoden
Management-Methoden bilden eine neue Kategorie von Methoden: sie
erlauben es, Laufzeitparameter ihrer Datentypen zu verändern und zu
optimieren.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
46
Zustandsmodifikatoren
RepräsentationsWechsler
ManagementMethoden
Netzmodifikatoren
Modifikatoren
(Mutatoren)
Zustandsverändernde
Methoden
Optimierer
Allgemeine
Methoden
einer Familie von anderen Klassen arbeiten
– Hier: java.util.Collections enthält Algorithmen auf beliebigen
Klassen, die das Collection- bzw. List-Interface implementieren
– Bei manchen Operationen ist Ordnung auf Elementen
vorausgesetzt.
– Achtung: Statische Klassenoperationen!
•Algorithmenklassen (Hilfsklassen) enthalten Algorithmen, die auf
file://localhost/Users/ua1/Courses/ST1/Material/jdk-docs/api/java/util/Collections.html
public
public class
class Collections<E>
Collections<E> {{
public
public static
static EE max
max (Collection<E>
(Collection<E> coll);
coll);
public
static
public static EE min
min (Collection<E>
(Collection<E> coll);
coll);
public
static
int
binarySearch(List<E>
public static int binarySearch(List<E> list,
list, EE
key);
key);
public
static
void
reverse
(List<E>
list);
public static void reverse (List<E> list);
public
public static
static void
void sort
sort (List<E>
(List<E> list)
list)
...
...
}}
Algorithmenklassen
Algorithmenklassen(Hilfsklassen)
(Hilfsklassen)enthalten
enthaltenAlgorithmen,
Algorithmen,
die
dieauf
aufeiner
einerFamilie
Familievon
vonanderen
anderenKlassen
Klassenarbeiten
arbeiten
Standardalgorithmen in der Algorithmenklasse
java.util.Collections
Tester
Checker
Zustandsinvariante
Methoden
Methode
Erweiterung: Taxonomie der Methodenarten
Anfrage (query)
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
45
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
47
48
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Schnittstelle
(interface)
Abstrakte Klasse
Algorithmenklasse
(Konkrete) Klasse
►
►
►
Clonable
Serializable
–
–
Resultat ist kleiner/gleich/größer 0:
genau dann wenn "this" kleiner/gleich/größer als Objekt o
public
public interface
interface Comparable<E>
Comparable<E> {{
public
public int
int compareTo
compareTo (E
(E o);
o);
}}
Beispiel: geordnete Standarddatentypen (z.B. String oder List)
implementieren die Prädikatschnittstelle Comparable:
Iterable
–
Prädikat-Schnittstellen drücken bestimmte Eigenschaft einer Klasse aus.
Sie werden oft mit dem Suffix “able” benannt:
Prädikat-Schnittstellen (...able Schnittstellen)
Generische Klasse
Partielle
Klasse
Klasse
Begriffshierarchie von Klassen (Erweiterung)
49
50
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prädikatschnittstellen können für einen Typparameter einfache Prädikate
ausdrücken
Beispiel: Comparable<E> als Return-typ in der Collections-Klasse sichert zu,
dass die Methode compareTo() existiert
Generische Klasse
Prädikat-Schnittstelle
Schnittstelle
(interface)
Abstrakte Klasse
Partielle
Klasse
Klasse
Algorithmenklasse
(Konkrete) Klasse
Begriffshierarchie von Klassen (Erweiterung)
public static <E extends Comparable<E>> min(Collection<E> ce) {
public static <E extends Comparable<E>> min(Collection<E> ce) {
Iterator<E> iter = ce.iterator();
Iterator<E> iter = ce.iterator();
E curMin = iter.next;
E curMin = iter.next;
if (curMin == null) return curMin;
if (curMin == null) return curMin;
for (E element = curMin;
for (E element = curMin;
iter.hasNext(), element = iter.next) {
iter.hasNext(), element = iter.next) {
if (element.compareTo(curMin) < 0) {
if (element.compareTo(curMin) < 0) {
curMin = element;
curMin = element;
}
}
}
}
return curMin;
return curMin;
}
}
class Collections {
class Collections {
/** minimum function for a Collection. Return value is typed
/** minimum function for a Collection. Return value is typed
* with a generic type with a type bound */
* with a generic type with a type bound */
►
►
Typschranken generischer Parameter (type
bounds), mit Prädikatsschnittstellen
52
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
E
E
LinkedList<E>
ArrayList<E>
E
K,V
K,V
TreeMap<K,V>
E
HashMap<K,V>
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
TreeSet<E>
HashSet<E>
E
<<interface>>
SortedSet<E>
E
<<interface>>
Set<E>
E
<<interface>>
List<E>
<<interface>>
Collection<E>
E
Mengen (ohne Mehrfacheintrag)
im Collection Framework
51
21.5 Ungeordnete Collections
mit Set
53
54
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
►
// Zustandsveränderer
+ boolean add (E o);
// Query methods
+ E get(int index);
<<interface>>
Set<E>
+ preis(): int
Artikel
– name: String
– preis: int
* {unordered}
+ add (a: Artikel)
+ anzahl(): int
1
Warengruppe
– name: String
– lagerplatz: String
Set<E>
Eine Assoziation in UML kann als {unordered} gekennzeichnet sein
Anwendungsbeispiel für Set<E>
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
<<interface>>
Collection<E>
Ungeordnete Mengen: java.util.Set<E> (Auszug)
<<interface>>
Collection<E>
56
<<class>>
HashSet<E>
}
public String toString() {
String s = "Warengruppe "+name+"\n";
Iterator it = inhalt.iterator();
while (it.hasNext()) {
s += " "+(Artikel)it.next();
};
}
Online:
Warengruppe0.java
public int anzahl() { return inhalt.size(); }
public void add (Artikel a) { inhalt.add(a); }
public Warengruppe
(String name, String lagerplatz) {
this.name = name;
this.lagerplatz = lagerplatz;
this.inhalt = new HashSet<Artikel>();
}
private String name;
private String lagerplatz;
private Set<Artikel> inhalt;
class Warengruppe {
Anwendungsbeispiel mit HashSet<E>
// Zustandsveränderer
+ boolean add (E o);
// Konstruktor
# HashSet<E>(int initialCapacity,
float loadFactor);
+ E get(int index);
+ int hashCode()
// Zustandsveränderer
+ boolean add (E o);
(Anmerkung: Erläuterung von Hashfunktionen
folgt etwas später !)
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
// Query methods
+ E get(int index);
<<interface>>
Set<E>
Konkreter Datentyp
java.util.HashSet<E> (Auszug)
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
55
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
57
58
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Typischer Fehler: Stringvergleich mit "=="
(ist nicht korrekt, geht aber meistens gut!)
z.B. java.lang.String
bei Bedarf selbst überdefinieren !
●
(Ggf. für kompatible Definition der Operation o.hashCode() aus
java.lang.Object sorgen)
Standardbedeutung Referenzgleichheit
●
für selbstdefinierte Klassen
●
überdefiniert in vielen Bibliotheksklassen
–
–
deklariert in java.lang.Object
–
Alternative: Vergleich mit Gleichheitsfunktion o.equals():
–
Der Vergleich mit Operation == prüft auf Referenzgleichheit, d.h.
physische Identität der Objekte
Online:
Warengruppe0.java
Warengruppe Moebel
Tisch(200) Tisch(200) Schrank(300) Stuhl(100)
Systemausgabe beim Benutzen der Standard-Gleichheit:
public static void main (String[] args) {
Warengruppe w1 = new Warengruppe("Moebel","L1");
w1.add(new Artikel("Tisch",200));
w1.add(new Artikel("Stuhl",100));
w1.add(new Artikel("Schrank",300));
w1.add(new Artikel("Tisch",200));
System.out.println(w1);
}
Wann sind Objekte gleich? (2)
Referenzgleichheit
►
►
Duplikatsprüfung für Elemente in Mengen:
Wann sind Objekte gleich? (1)
59
<<interface>>
Collection<E>
// Zustandsveränderer
+ boolean add (E o);
+ boolean remove (E o);
+ void clear();
// Repräsentations-Trans// formierer
+ E[] toArray();
+ E first();
+ E last()
// Zustandsveränderer
+ boolean add (E o);
// Query methods
+ E get(int index);
<<interface>>
Set<E>
<<interface>>
SortedSet<E>
Es wurde zweifach dasselbe Tisch-Objekt übergeben !
(Gleiches Verhalten bei Strukturgleichheit, s. Warengruppe1.java)
Online:
Online:
Warengruppe1.java Warengruppe2.java
Warengruppe Moebel
Schrank(300) Tisch(200) Stuhl(100)
Systemausgabe bei Referenzgleichheit:
java.util.SortedSet<E> (Auszug)
}
Warengruppe w2 = new Warengruppe("Moebel","L2");
w2.add(tisch);
w2.add(stuhl);
w2.add(schrank);
w2.add(tisch);
System.out.println(w1);
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Wann sind Objekte gleich? (3)
Referenzgleichheit
// Query methods
+ boolean isEmpty();
+ boolean contains(E o);
+ boolean equals(E o);
+ int hashCode();
+ Iterator iterator();
60
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
61
62
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Aber Systemreaktion:
Exception in thread "main" java.lang.ClassCastException: Artikel
at java.util.TreeMap<K,V>.compare(TreeMap<K,V>.java, Compiled Code)
in java.util.TreeSet<E>:
public class TreeSet<E> … implements SortedSet<E> … { … }
Modifikation der Klasse „Artikel“:
►
Online:
Warengruppe3.java
Warengruppe Moebel
Schrank(300) Stuhl(100) Tisch(200)
Systemausgabe:
class Artikel implements Comparable<Artikel> {
...
public int compareTo (Artikel o) {
return name.compareTo(o.name);
}
}
Artikel muss von Schnittstelle Comparable<Artikel> erben
►
Anwendungsbeispiel mit TreeSet<E>
►
►
Modifi kation der konkreten Klasse Warengruppe:
►
class Warengruppe<E> {
private Set<E> inhalt;
public Warengruppe (…) {
…
this.inhalt = new TreeSet<E>();
} …
}
java.util.TreeSet<E> implementiert ein geordnete Menge mit Hilfe eines
Baumes und benötigt zum Sortieren dessen die Prädikat-Schnittstelle
Comparable<E>
►
Sortierung von Mengen mit TreeSet nutzt
Vergleichbarkeit von Elementen
63
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
in allen Fällen schneller !
–
106,5
177,4
Enthalten
39,39
40,04
Iteration
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
21.6 Kataloge mit Map
erlaubt Operationen für sortierte Mengen
Stärken von TreeSet:
–
Stärken von HashSet:
36,14
150,6
64
►
►
Einfügen
HashSet
TreeSet
Gemessener relativer Aufwand für Operationen auf Mengen:
(aus Eckel, Thinking in Java, 2nd ed., 2000)
Typ
►
HashSet oder TreeSet?
65
66
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
E
E
K,V
K,V
TreeMap<K,V>
E
TreeSet<E>
HashMap<K,V>
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
// Zustandsveränderer
+ void clear();
+ V put (K key, V value);
+ boolean remove (V o);
<<class>>
HashMap<K,V>
Map liefert funktionale Abhängigkeit zwischen Schlüssel und Wert
–
<<interface>>
Map<K,V>
Ein Schlüssel liefert einen Wert (Funktion).
–
Eine Map ist ein „assoziativer Speicher“ (associative array), der Objekte als
Werte (value) unter Schlüsseln (key) zugreifbar macht
// Anfragen (query methods)
+ int size();
+ boolean isEmpty();
+ boolean containsKey(K key);
+ boolean containsValue(V value);
+ V get (K key);
+ int hashCode();
+ Iterator iterator();
+ Set<K> keySet<E>();
+ Set<V> values();
►
E
HashSet<E>
java.util.Map<K,V> (Auszug)
LinkedList<E>
ArrayList<E>
<<interface>>
SortedSet<E>
E
<<interface>>
Set<E>
E
<<interface>>
List<E>
<<interface>>
Collection<E>
E
Collection Framework (Überblick) (Maps)
67
68
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
HashMap ist eine sehr günstige
Umsetzung für qualifizierte
Assoziationen:
Der Qualifikator bildet den
Schlüssel; die Zielobjeke den Wert
Hier:
►
Schlüssel: code:String
►
Wert: a:Artikel
►
►
class
class Katalog
Katalog {{
private
private String
String name;
name;
private
private Map<String,Artikel>
Map<String,Artikel> inhalt;
inhalt; //
// Polymorphe
Polymorphe Map
Map
public
Katalog
(String
public Katalog (String name)
name) {{
this.name
this.name == name;
name;
this.inhalt
this.inhalt == new
new HashMap<
HashMap<String,Artikel
String,Artikel>();
>();
}}
public
public void
void put
put (String
(String code,
code, Artikel
Artikel a)
a) {{
inhalt.put(code,a);
inhalt.put(code,a);
}}
public
public int
int anzahl()
anzahl() {{
return
return inhalt.size();
inhalt.size();
}}
public
public Artikel
Artikel get
get (String
(String code)
code) {{
return
return (Artikel)inhalt.get(code);
(Artikel)inhalt.get(code);
}}
...
...
}}
Online:
Katalog.java
Anwendungsbeispiel mit HashMap
+ preis(): int
1
Artikel
– name: String
– preis: int
*
code: String
Katalog
– name: String
+ put (code: String, a: Artikel)
+ get (code: String): Artikel
+ anzahl(): int
Anwendungsbeispiel: Verfeinerung von
qualifizierten Assoziationen in UML
69
70
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
■
■
■
value: V
V
key: K
K
hashCode(): int
key.hashCode()
hashcode
%
capacity
entry index
0
value: V
hashtab
Mit dem Eintragswert wird in eine Hashtabelle eingestochen
Der Hashwert wird auf einen Zahlenbereich modulo der Kapazität der Hashtabelle
abgebildet, d.h., der Hashwert wird auf die Hashtabelle “normiert”
Das Objekt liefert seinen Hashwert mit der Hash-Funktion hashCode()
Typischerweise wird der Schlüssel (key) transformiert:
Object
►
Effekt von hashtab.put(key:K,value:V)
Prinzip der Hashtabelle
Ordnung auf den Schlüsseln: SortedMap (Implementierung z.B.TreeMap).
put(...) überschreibt vorhandenen Eintrag (Ergebnis = vorhandener Eintrag).
}
Katalog k = new Katalog("Katalog1"); Systemausgabe:
k.put("M01",tisch);
Katalog Katalog1
k.put("M02",stuhl);
M03 -> Schrank(300)
M02 -> Stuhl(100)
k.put("M03",schrank);
M01 -> Tisch(200)
System.out.println(k);
Katalog Katalog1
k.put("M03",regal);
M03 -> Regal(200)
M02 -> Stuhl(100)
System.out.println(k);
M01 -> Tisch(200)
public static void main (String[] args) {
Artikel tisch = new Artikel("Tisch",200);
Artikel stuhl = new Artikel("Stuhl",100);
Artikel schrank = new Artikel("Schrank",300);
Artikel regal = new Artikel("Regal",200);
Testprogramm für Anwendungsbeispiel:
Speicherung der Waren mit Schlüsseln
71
value2: V
key2: K
value1: V
capacity
key1.hashCode()
= key2.hashCode()
0
value?: V
72
E
E
E
Vector<E>
LinkedList<E>
ArrayList<E>
E
K,V
Hashtable<K,V> TreeMap<K,V>
K,V
K,V
HashMap<K,V>
E
TreeSet<E>
K,V
<<interface>>
SortedMap<K,V>
<<interface>>
Map<K,V>
K,V
Implementierung (implements)
Vererbung (extends)
HashSet<E>
E
<<interface>>
SortedSet<E>
E
<<interface>>
Set<E>
E
<<interface>>
List<E>
<<interface>>
Collection<E>
E
Weitere Implementierungen in der CollectionHierarchie
In Java werden in den HashMap-Implementierungen spezielle
Auslastungsfaktoren (load factors) berücksichtigt. Standardmäßig wird
eine HashMap ab einer Auslastung von 75% automatisch neu
organisiert.
Beispiel mit Hashtabelle für Strings und Länge als Hashfunktion.
Generell ist es wünschenswert, möglichst wenig Kollisionen zu haben.
Dies kann z.B. durch eine geschickt gewählte, weit streuende
Hashfunktion und ein günstiges Verhältnis Tabellengröße:Datenmenge
erreicht werden.
• Verwendung einer „Überlaufliste“
• dito, mit steigender Schrittweite bei Iteration
Überlaufliste
Bei nicht eindeutigen Schlüsseln, oder auch durch die Normierung, werden
Einträge doppelt “adressiert” (Kollision)
key1: K
–
Die Hashfunktion ist mehrdeutig (nicht injektiv):
Verfahren zur Kollisionsauflösung:
Überlauflisten (z.B. mit List)
Überlaufbaum (TreeSet)
Überlauf in der Hashtabelle
►
Kollision beim Einstechen
Möglichkeiten zur Kollisionsauflösung:
• Verwendung des nächsten Felds der Tabelle, iterativ
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
74
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
►
►
{ordered} {unordered}
{unique} {non-unique}
{set} {bag} {sequence}
{union} {subsets}
Ordnung:
Eindeutigkeit:
Kollektionsart:
Zusammenhang:
Duplikate
mit Duplikaten
ohne Duplikate
Ordnung
geordnet
ungeordnet
sortiert
unsortiert
Sortierung
mit Schlüssel
ohne Schlüssel
Schlüssel
Beim Übergang zum Implementierungsmodell müssen diese Bedingungen
auf Unterklassen von Collections abgebildet werden
■
■
■
■
An das Ende einer UML-Assoziation können folgende Bedingungen notiert
werden:
Facetten und Assoziationsarten
73
21.7 Optimierte Auswahl von
Implementierungen von
Datenstrukturen
Funktion
75
76
Anpassung an
vorgefertigte Lösung
Entwicklung
Entwicklungeiner
einer
neuartigen
neuartigenLösung
Lösung
Effizienz-Verbesserung:
Effizienz-Verbesserung:Ggf.
Ggf.Experimente
Experimentemit
mitLaufzeiten,
Laufzeiten,
Speicherverbrauch,
Speicherverbrauch,Energieverbrauch
Energieverbrauch
Suche nach vorgefertigten Lösungen
(Nutzung der Collection-Bibliothek)
Abstraktion auf die wesentlichen Eigenschaften
Identifikation
Identifikationder
derfunktionalen
funktionalenAnforderungen
Anforderungenan
andie
dieDatenstruktur:
Datenstruktur:
Facetten
Facettender
derFunktionalität,
Funktionalität,häufig
häufigbenutzte
benutzteOperationen
Operationen(Benutzungsprofil)
(Benutzungsprofil)
Vorgehensweise beim funktionalen und
effizienzbasierten Datenstruktur-Entwurf
ja
Entfernen an i-ter Position
Ersetzen an i-ter Position
Abfrage an i-ter Position
List<E>
nein
Einfügereihenfolge relevant?
Elemente doppelt?
Collection<E>
Einfügen eines Elements
Entfernen eines Elements
Aufzählen aller Elemente
"ist enthalten"-Abfrage
dynamisch erweiterbar
SortedMap<K,V>
Sortierung relevant?
Elemente "über"/"unter" x
kleinstes/größtes Element
SortedSet<E>
Set<E>
Sortierung der
Schlüssel relevant?
dynamisch erweiterbar
"ist enthalten"-Abfrage für Schlüssel
Abfrage eines Werts für einen Schlüssel
Entfernen eines Schlüssel/Wert-Paars
Einfügen eines Werts für einen Schlüssel
Map<K,V>
Suche nach vorgefertigten Lösungen (anhand der
Facetten der Collection-Klassen)
Effizienz
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
77
78
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
inhalt
* {mod}
Artikel (Z)
Realisierung
Set<E>
5) Maximalanzahl der Elemente
unbekannt;
dynamisch erweiterbar
4) "ist enthalten"-Abfrage
1) Einfügen (ohne Reihenfolge)
2) Entfernen (ohne Reihenfolge)
3) Aufzählen aller Elemente
* {unique}
inhalt
Artikel (Z)
}
public A {
assoc = new HashSet<Z>();
}
public boolean testAssoc (Z ziel) {
return assoc.contains(ziel);
}
class A {
private Set<Z> assoc;
...
public void addAssoc (Z ziel) {
assoc.add(ziel);
}
Warengruppe (A)
Realisierung von ungeordneten Assoziationen mit
Set<E>
1) Assoziation anlegen
2) Assoziation entfernen
3) Durchlaufen aller bestehenden
Assoziationen zu Z-Objekten
4) Manchmal: Abfrage, ob
Assoziation zu einem
Z-Objekt besteht
5) Keine Obergrenze der
Multiplizität gegeben
Anforderung
Datenstruktur im A-Objekt für Z-Referenzen
Warengruppe (A)
Beispiel: Realisierung von unidirektionalen
Assoziationen
79
►
►
►
80
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
* {unique,
sorted}
inhalt
Artikel (Z)








Analyse
Dann der beta-Test
Zum Schluss der
Akzeptanztest (Abnahmetest)
Dann das Netz testen
Dann die Komponente
Dann das System
Verträge und Testfälle für das Netz
entwerfen
Dann die einzelne Klasse testen
Testfälle
Testfälle
Testfälle
Objektimplementierung
Objektimplementierung
Netzimplementierung
Netzimplementierung
Testfälle
Feinentwurf
Feinentwurf
Verfeinerung von Assoziationen
Grobentwurf
Grobentwurf
Zuerst Verträge und Testfälle für die
Klasse bilden
Analyse
Die Tests werden bottom-up erledigt:
Netze werden im Grob- und
Feinentwurf in UML modelliert
In der Phase “Netzimplementierung” in
Java umgesetzt
Systemtest
Abnahmetest
Netztest
Netztest
Integrationstest
Komponententest
Zusicherungen
Zusicherungen
Methodentest
Methodentest
Klassentest
Klassentest
Ziel: V-Modell mit Standard-Testprozess
mit Netz-Entwurf und -Test
}
public A {
assoc = new TreeSet<Z>();
}
public boolean testAssoc (Z ziel) {
return assoc.contains(ziel);
}
class A {
private Set<Z> assoc;
...
public void addAssoc (Z ziel) {
assoc.add(ziel);
}
Warengruppe (A)
Realisierung von sortierten Assoziationen mit
Set<E>
81
82
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Weniger Casts, mehr Typsicherheit
■
Die Java Collection Library bietet geordnete, ungeordnete Collections sowie
Kataloge
Element-Typ verfeinert Object
■
Static vs. dynamic vs. no typing
Safe Application Development (SAD) nur mit statischen Typisierung möglich
Rapid Application Development (RAD) benötigt dynamische Typisierung
Generische Collections besitzen den Element-Typ als Typ-Parameter
►
Diese Folien bauen auf der Vorlesung Softwaretechnologie auf von © Prof.
H. Hussmann, 2002. Used by permission.
The End
►
►
►
►
►
Was haben wir gelernt
84
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
// Das Archiv listOfRechnung fasst die Rechnungen des
// Das Archiv listOfRechnung fasst die Rechnungen des
// aktuellen Jahres zusammen
// aktuellen Jahres zusammen
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<Rechnung> listOfRechnung = new ArrayList<Rechnung>();
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>;
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>;
archiv.add(listOfRechnung);
archiv.add(listOfRechnung);
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
funktioniert
archiv.get(0).add(rechnung);
archiv.get(0).add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
archiv.get(0).add(best);
Übersetzungsarchiv.get(0).add(best);
Fehler
for (int jahr = 0; jahr < archiv.size(); jahr++) {
for (int jahr = 0; jahr < archiv.size(); jahr++) {
listOfRechnung = archiv.get(jahr);
listOfRechnung = archiv.get(jahr);
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = listOfRechnung.get(i);
rechnung = listOfRechnung.get(i);
}
}
}
}
Generizität auf Containern
funktioniert auch geschachtelt
83
Appendix A
Generische Command Objekte
85
86
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
.. ist ab Java 1.5 ohne Probleme nebeneinander möglich
funktioniert
►
►
►
Übersetzt auch,
aber Laufzeitfehler
beim Cast...
z.B. sind alle Instanzen mit unboxed objects als boxed objects realisiert
–
}
T attribute<T>
Templateparameter können Variablen umbenennen
C++ bietet Code-Templates (snippets, fragments) an, mit denen man mehr
parameterisieren kann, z.B. Methoden
In C++ können Templateparameter Variablen umbenennen:
template class C <class T> {
Verliert etwas Effizienz, da der Übersetzer alle Typinformation im generierten
Code vergisst und nicht ausnutzt
–
In Java: einmalige Übersetzung des generischen Datentyps
Unterschiede zu C++
for (int jahr = 0; jahr < archiv.size(); jahr++) {
for (int jahr = 0; jahr < archiv.size(); jahr++) {
listOfRechnung = archiv.get(jahr);
listOfRechnung = archiv.get(jahr);
for (int i = 0; i < listOfRechnung.size(); i++) {
for (int i = 0; i < listOfRechnung.size(); i++) {
rechnung = (Rechnung)listOfRechnung.get(i);
rechnung = (Rechnung)listOfRechnung.get(i);
}
}
}
}
archiv.add(listOfRechnung);
archiv.add(listOfRechnung);
Rechnung rechnung = new Rechnung();
Rechnung rechnung = new Rechnung();
archiv.get(0).add(rechnung);
archiv.get(0).add(rechnung);
Bestellung best = new Bestellung();
Bestellung best = new Bestellung();
archiv.get(0).add(best);
archiv.get(0).add(best);
// Das Archiv fasst alle Rechnungen aller bisherigen Jahrgänge zusammen
// Das Archiv fasst alle Rechnungen aller bisherigen Jahrgänge zusammen
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>();
List<List<Rechnung>> archiv = new ArrayList<List<Rechnung>>();
// listOfRechnung fasst die Rechnungen des aktuellen Jahres zusammen
// listOfRechnung fasst die Rechnungen des aktuellen Jahres zusammen
List listOfRechnung = new ArrayList();
List listOfRechnung = new ArrayList();
►
Benutzung von getypten und ungetypten
Schnittstellen
87
88
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Es gibt eine Standard-Funktion in der Klasse des Funktionalobjektes, das die
Berechnung ausführt (Standard-Name, z.B. execute() oder doIt())
// A functional object that is like a constant
// A functional object that is like a constant
interface NullaryOpCommand { void execute();
interface NullaryOpCommand { void execute();
void undo(); }
void undo(); }
// A functional object that takes one parameter
// A functional object that takes one parameter
interface UnaryOpCommand<P> { P execute(P p1);
interface UnaryOpCommand<P> { P execute(P p1);
void undo(); }
void undo(); }
// A functional object that operates on two parameters
// A functional object that operates on two parameters
interface BinOp<P> { P execute(P p1, P p2);
interface BinOp<P> { P execute(P p1, P p2);
void undo(); }
void undo(); }
Zur Laufzeit kann man das Funktionalobjekt mit Parametern
versehen, herumreichen, und zum Schluss ausführen
–
Funktionalobjekte können Berechnungen kapseln und später
ausführen (laziness) (Entwurfsmuster Command)
B
C,E
Accumulate
Functional
P
// An interface for a collection of binary operation on
// An interface for a collection of binary operation on
// collections
// collections
interface Functional<Collection<P>,B extends BinOp<P>> {
interface Functional<Collection<P>,B extends BinOp<P>> {
P compute(Collection<P> p);
P compute(Collection<P> p);
}
}
class Accumulate<C,E> implements Functional<C,BinOp<E>> {
class Accumulate<C,E> implements Functional<C,BinOp<E>> {
E curSum;
E element;
BinOp<E> binaryOperation;
E curSum;
E element;
BinOp<E> binaryOperation;
public E compute(C coll) {
public E compute(C coll) {
for (int i = 0; i < coll.size(); i++) {
for (int i = 0; i < coll.size(); i++) {
element = coll.get(i);
element = coll.get(i);
curSum = binaryOperation.execute(curSum,element);
curSum = binaryOperation.execute(curSum,element);
}
}
return curSum;
return curSum;
}
}
}
}
Anwendung: Akkumulatoren und andere generische Listenoperationen
BinOp
►
Generische Methoden als Funktionale Objekte
►
►
Ein Funktionalobjekt (Kommandoobjekt) ist ein Objekt, das eine Funktion
Ein Funktionalobjekt (Kommandoobjekt) ist ein Objekt, das eine Funktion
darstellt (reifiziert).
darstellt (reifiziert).
Implementierungsmuster Command:
Generische Methoden als Funktionale Objekte
Collection
<P>
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Softwaretechnologie, © Prof. Uwe Aßmann
Technische Universität Dresden, Fakultät Informatik
90
* *
Privater
Termin
Privater
beschreibg
Termin
beginn
beschreibg
dauer
beginn
dauer
ort
ort
wegzeit
wegzeit
genehmigen()
genehmigen()
verschieben()
verschieben()
Termin
Termin
*
0..1 Ort
Teambesprechung
*
titel
Teambesprechung
beginn
titel
dauer
beginn
anzahl
dauer
name
1
Team
0..1
name
0..1
1 Leiter
10..*
1Teammitglied
Leiter
leitet10..*
*
leitet
1
Teammitglied
anzahl
name
raumFestlegen()
1
name abteilung
raumFestlegen()
einladen()
abteilung
Teilnahme
einladen()
Teilnahme
terminBestätigen()
absagen()
terminBestätigen()
absagen()
* 2..*
2..*
verschieben() *
verschieben()
1
1
für
für
*
1
Besprechungsraum
reservieren()
raumNr
freigeben()
kapazität
freienRaumSuchen()
reservieren()
0..1
Ort
freigeben()
Team
freienRaumSuchen()
raumNr
kapazität
Beispiel 2: AnalysemodellBesprechungsraum
der Terminverwaltung
Beispiel 2: Analysemodell der Terminverwaltung
89
Appendix B
Bestimmung von konkreten
Datentypen
Operationen werden in der Vorlesung interaktiv eingetragen.
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
90
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
91
92
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
Prof. U. Aßmann, Softwaretechnologie, TU Dresden
» SortedSet<Besprechungsraum> (Elemente: Besprechungsraum)
Datenstruktur für vorhandene Räume in Klasse Raumverwaltung
Datenstruktur in Klasse Besprechungsraum für Zeiten (Stunden):
–
–
TerminvTreeSet.java
» Map<Hour,Teambesprechung> (Schlüssel: Hour, Wert:
Teambesprechung)
Online:
Datenstruktur in Klasse Besprechungsraum:
Zusatzanforderung (Variante): Überprüfung, welcher andere Termin eine
bestimmte Stunde belegt.
» Set<Hour> (Elemente: Hour)
Operation in Klasse Besprechungsraum:
boolean frei (Hour beginn, int dauer )
–
Überprüfung eines Raumes, ob er für die Zeit ab beginn für die Länge
dauer bereits belegt ist.
–
Suche unter vorhandenen Räumen nach Raum mit mindestens der
Kapazität groesse, aber möglichst klein.
}
// Suche freien Raum aufsteigend nach Größe
static Besprechungsraum freienRaumSuchen
(int groesse, Hour beginn, int dauer) {
Besprechungsraum r = null;
boolean gefunden = false;
Iterator it = vorhandeneRaeume.iterator();
while (! gefunden && it.hasNext()) {
r = (Besprechungsraum)it.next();
if (r.grossGenug(groesse)&& r.frei(beginn,dauer))
gefunden = true;
};
if (gefunden) return r;
else
return null;
} ...
class Raumverwaltung {
// Vorhandene Raeume, aufsteigend nach Größe sortiert
// statisches Klassenattribut und -methode
private static SortedSet<E> vorhandeneRaeume
= new TreeSet<Besprechungsraum>();
Raumverwaltung: Freien Raum suchen
►
►
►
static Besprechungsraum freienRaumSuchen
(int groesse, Hour beginn, int dauer)
Beispiel 2: Sortierte Liste von Räumen in der
Raumverwaltung
Herunterladen