Java Collection Framework - DBIS Informatik

Werbung
Java Collection Framework
Programmiermethodik
Eva Zangerle
Universität Innsbruck
Überblick
Einführung
Java – Ein erster Überblick
Objektorientierung
Vererbung und Polymorphismus
Ausnahmebehandlung
Pakete und Javadoc
Spezielle Themen
Generische Programmierung
Einleitung
Ausgewählte Klassen
Java Collection-Framework
Streams
Unit-Tests
Iteratoren
Wichtige Themen
Entwurfsmuster - Eine Einführung
GUI-Programmierung
Java Virtual Machine
Ausblick
Programmiermethodik - Java Collections
2
Einleitung
Motivation
• Programmierer benötigt sehr oft bestimmte
Datenstrukturen.



Datenstrukturen sollten schon vorhanden sein.
Datenstrukturen sollten generisch sein.
Allgemeine Algorithmen (anwendbar auf unterschiedliche
Datenstrukturen) sollten vorhanden sein.
• Lösung?

Java Collection-Framework
Programmiermethodik - Java Collections
4
Grundlagen
• Collection-Framework befindet sich im Paket java.util.
• Für unterschiedliche Datenstrukturen stehen
unterschiedliche Interfaces zur Verfügung.



Die Interfaces geben die Schnittstellen für den Zugriff auf die
Datenstrukturen an (z.B. Einfügen in Listen).
Die konkrete Verwaltung wird durch konkrete Implementierungen
dieser Interfaces bestimmt.
Seit Java 1.5 ist das Collection-Framework generisch.
• Jedes Interface kann durch unterschiedliche
Implementierungen unterstützt werden (z.B. LinkedList,
ArrayList).
• Es gibt Algorithmen, die auf Collection-Objekte (Listen etc.)
angewandt werden können (z.B. Sortieren).
Programmiermethodik - Java Collections
5
Interfaces (Überblick)
• Interfaces sind die Grundlage (java.util.Collection oder
java.util.Map)



Basisoperationen (Hinzufügen, Finden, etc.)
Mengenoperationen (andere Collection einfügen)
Feldoperationen (z.B. andere Ansichten auf key/value)
• Applikationen sollten ihren Code ausschließlich auf Interfaces
aufbauen  Austauschbarkeit.
• Interfaces bilden Hierarchien.
Programmiermethodik - Java Collections
6
Collection – Interfaces (Seit 1.5)
Collection
• Eine Collection verwaltet Objekte (Elemente).
• Interface enthält generelle Methoden (für alle Collection-Typen).
• Es gibt keine direkte Implementierung dieses Interfaces.
Set
• Eine Collection die keine duplizierten Elemente enthält.
List
• Eine geordnete Collection (mit duplizierte Elementen)
• Elemente können über einen Index angesprochen werden (nicht
immer effizient).
Queue
Map
SortedSet und
SortedMap
Programmiermethodik - Java Collections
• Verwaltung von Warteschlangen (ähnlich zu Listen)
• FIFO, Prioritätswarteschlangen
• Maps verwalten Schlüssel mit dazugehörigen Werten.
• Schlüssel sind eindeutig.
• Jeder Schlüssel kann einen dazugehörigen Wert haben.
• Sind spezielle Versionen von Set und Map, bei denen die
Elemente (Schlüssel) in aufsteigender Reihenfolge verwaltet
werden.
7
Implementierung
• Es gibt unterschiedliche Ansätze für die Implementierung von
konkreten Collection-Klassen:
Generelle Implementierungen, die häufig in Applikationen
verwendet werden.
 Spezielle Implementierungen
 Nebenläufige Implementierungen (für Multithreaded-Applikationen,
siehe Entwurf von Softwaresystemen).
 Wrapper-Implementierungen, die mit anderen Implementierungen
benutzt werden (oft generelle Implementierungen) und zusätzliche
oder eingeschränkte Funktionalität zur Verfügung stellen.
 Einfache effiziente Implementierungen (Mini-Implementierungen)
für spezielle Collections.
 Abstrakte Implementierungen, die ein Implementierungsskelett zur
Verfügung stellen und damit die Implementierung eigener CollectionKlassen erleichtern.

Programmiermethodik - Java Collections
8
Generelle Implementierungen (1)
Implementierungen
Interface
Hashtabellen
Set
HashSet
List
Dynamische
Arrays
Bäume
TreeSet
ArrayList
HashTabellen
+
Verkettete
Listen
LinkedHashSet
LinkedList
Queue
Map
Verkettete
Listen
LinkedList
HashMap
Programmiermethodik - Java Collections
TreeMap
LinkedHashMap
9
Generelle Implementierungen (2)
• Es existieren generelle Implementierungen für die Interfaces
Set, List und Map.
• Interfaces SortedSet und SortedMap werden von
TreeSet bzw. TreeMap zusätzlich implementiert.
• Queue-Interface wird z.B. von den folgenden Klassen
implementiert:


LinkedList – FIFO Warteschlangen
PriorityQueue – Prioritätswarteschlange (ist eher eine spezielle
Implementierung)
Programmiermethodik - Java Collections
10
Seit Java 1.6
• Deque (Double ended queue)


Einfügen und Löschen an beiden Enden
Wird u.a. von der Klasse LinkedList implementiert.
• NavigableSet und NavigableMap


Sollen SortedSet und SortedMap ersetzen.
Sind Erweiterungen, die das Navigieren (aufsteigend, absteigend)
erlauben.
• Zusätzliche nebenläufige Implementierungen (siehe Entwurf
von Softwaresystemen)
• Zusätzliche Hilfsmethoden
Programmiermethodik - Java Collections
11
Ausgewählte Klassen
Eigenschaften ausgewählter Klassen
ArrayList
LinkedList
• Indexzugriff auf Elemente ist überall ungefähr gleich schnell.
• Einfügen und Löschen ist am Listenende schnell und wird mit wachsender
Entfernung vom Listenende langsamer.
• Indexzugriff auf Elemente ist an den Enden schnell und wird mit der Entfernung
von den Enden langsamer.
• Einfügen und Löschen ohne Indexzugriff ist überall gleich schnell.
• Ansonsten abhängig vom Indexzugriff.
HashSet
• null-Elemente sind zulässig.
• Einfügen, Suchen und Löschen sind immer gleich schnell.
• Aber: Rehashing kann zu Performance-Problemen führen (siehe auch APIBeschreibung).
TreeSet
• null-Elemente sind nicht erlaubt.
• Die Geschwindigkeit von Einfügen, Suchen und Löschen ist proportional zum
Logarithmus der Anzahl der Elemente.
• Auf die Elemente eines TreeSets muss eine Ordnung definiert sein (müssen
vergleichbar sein, d.h. das Interface Comparable<T> implementieren).
Programmiermethodik - Java Collections
13
Methoden (Beispiele)
• Für Listen und Sets gibt es einige gemeinsame Methoden.
• Beispiele (T ist der Elementtyp)
int size()
boolean add(T t)
boolean remove(T t)
boolean contains(T t)
T get(int i)
T set(int i, T t)
int indexOf(T t)
Programmiermethodik - Java Collections
14
Beispiel
import java.util.ArrayList;
import java.util.List;
public final class CollectionTest1 {
private CollectionTest1() {
Immer
kleinstmöglichen
Typ verwenden!
}
public static void main(final String[] args) {
final List<Integer> cl = new ArrayList<Integer>();
for (int x = 1; x < 10; x++) {
cl.add(x);
Ausgabe
}
[1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(cl);
4
System.out.println(cl.get(3));
9
System.out.println(cl.size());
System.out.println(cl.remove(2));
3
System.out.println(cl);
[1, 2, 4, 5, 6, 7, 8, 9]
System.out.println(cl.contains(7));
true
System.out.println(cl.set(5, 22));
7
System.out.println(cl);
[1, 2, 4, 5, 6, 22, 8, 9]
System.out.println(cl.indexOf(22));
5
}
}
Programmiermethodik - Java Collections
15
Maps
• Arrays und Collections speichern einzelne Werte des
Elementtyps (über Indexwerte adressiert, Typ der Indexwerte
ist int).
• Maps sind eine Verallgemeinerung von Arrays mit einem
beliebigen Indextyp.

Beispiel Telefonbuch
 Name mit Telefonnummer verknüpft.
 „Indextyp“ ist daher String (Name).
• Map-Eintrag hat


einen Schlüssel (key)
und einen Wert (value).
Programmiermethodik - Java Collections
16
Maps (key-value)
• Jedem Schlüssel ist genau ein Wert zugeordnet.
• Eine Map ist eine Menge von Schlüssel-Werte Paaren.


Schlüssel müssen innerhalb einer Map eindeutig sein.
Werte müssen nicht eindeutig sein.
• Wie bei Sets gibt es grundsätzlich zwei Versionen.

HashMap
 Ungeordnet
 Hashing

TreeMap
 Geordnet
 Rot-Schwarz-Baum (balanciert)
• Bestimmte Methoden wie put, get, containsKey,
containsValue, remove etc. werden angeboten.
Programmiermethodik - Java Collections
17
Beispiel
import java.util.HashMap;
import java.util.Map;
public final class CollectionTest2 {
public static void main(final String[] args) {
final Map<String, Double> m = new HashMap<String, Double>();
m.put("PC 1", 1199.90);
m.put("Spiele-PC", 2500.00);
m.put("My-Cloud", 100000.00);
System.out.println(m);
System.out.println(m.get("PC 1"));
System.out.println(m.containsKey("PC 1"));
System.out.println(m.remove("PC 1"));
System.out.println(m);
}
}
Programmiermethodik - Java Collections
Ausgabe:
{Spiele-PC=2500.0, My-Cloud=100000.0, PC 1=1199.9}
1199.9
true
1199.9
{Spiele-PC=2500.0, My-Cloud=100000.0}
18
Maps (equals, hashcode)
• HashMap und andere Klassen des Collection-Frameworks
rufen die Methode equals auf, um die Gleichheit von
Schlüsselobjekten (Elementen) festzustellen.
• Weiters wird von einigen Klassen die Methode hashCode
verwendet.
• Daher sollten alle Klassen die Methoden equals und
hashCode überschreiben.
• Die von der Klasse Object geerbten Versionen dieser
Methoden sind selten ausreichend, weil sie nur die
Referenzen prüfen, den Inhalt aber ignorieren.
Programmiermethodik - Java Collections
19
Maps und Collections (1)
• Maps implementieren nicht das Interface Collection, sind
aber Teil des Collection-Frameworks.
• Maps und Collections können verknüpft werden.
• Methode keySet liefert die Menge aller Schlüssel einer Map
in Form eines Sets.
• Methode values liefert die Werte der Map.


Über die Organisation der Werte ist nichts bekannt.
Das Ergebnis ist vom Typ Collection.
Programmiermethodik - Java Collections
20
Maps und Collections (2)
• Die Methode entrySet liefert die Menge der Einträge der
Map.
• Der Elementtyp ist Map.Entry<K,V> für eine Map mit dem
Schlüsseltyp K und dem Werttyp V.
• Map.Entry definiert die Methoden:


getKey
getValue
• Maps kennen keine Iteratoren, Sets hingegen schon.
• Daher kann man auf diesem Wege über eine Map iterieren.
• Beispiel folgt!
Programmiermethodik - Java Collections
21
Maps und Collections (3)
• Die drei Methoden keySet, values und entrySet
erzeugen keine neue Collection.
• Sie liefern sogenannte Sichten („views“).
• Daher sind diese Methoden auch bei großen Datenmengen
sehr effizient.

Es werden keine Daten kopiert!
• Sichten greifen direkt auf die zugrunde liegende Map zu.
• Änderungen an den Sichten wirken sich auf die
darunterliegende Map aus und umgekehrt.
• Wird eine Map geändert, dann wirkt sich das auf alle Sichten
aus.
Programmiermethodik - Java Collections
22
Iteratoren
Iteratoren allgemein (1)
• Durchlaufen von Collections
• Iterator wird durch eine Methode (z.B. iterator)
angeboten (zurückgegeben).
• Ein Iterator bietet folgende Methoden an



hasNext – testet, ob es weitere Elemente gibt (true) oder nicht
(false).
next – liefert das nächste Element und rückt den Iterator gleichzeitig
um ein Element weiter, d.h. aufeinanderfolgende Aufrufe von next
liefern immer neue Elemente.
remove (optional) – entfernt das zuletzt zurückgegebene Element.
Programmiermethodik - Java Collections
24
Iteratoren allgemein (2)
• Iteratoren sind eine Verallgemeinerung von Indexwerten.
• Werden ähnlich wie Indexwerte verwendet, ihr innerer
Aufbau bleibt aber verborgen.
• Alle Iteratoren implementieren das generische Interface
Iterator<T>.
• Iteratoren haben den gleichen Elementtyp wie die zugrunde
liegende Collection.
Programmiermethodik - Java Collections
25
Eigenschaften von Iteratoren
• Ein Iterator läuft von Beginn an Element für Element durch eine
Collection (keine Sprünge, kein Start an beliebiger Stelle).
• Ein Iterator steht immer zwischen zwei Elementen (oder vor dem
ersten, nach dem letzten).
• Iterator ist verbraucht, wenn er am Ende angekommen ist (keine
Wiederverwendung).
• Für einen neuen Durchlauf muss ein neuer Iterator erzeugt
werden.
• Innerhalb einer Collection können gleichzeitig mehrere Iteratoren
unterwegs sein.
• Mehrere Iteratoren sind unabhängig voneinander und können
einzeln bewegt werden.
Programmiermethodik - Java Collections
26
Beispiel (ArrayList)
…
List<String> ls = new ArrayList<String>();
ls.add("A");
ls.add("B");
Muss übereinstimmen!
ls.add("A");
ls.add("B");
…
Iterator<String> is = ls.iterator();
while (is.hasNext()){
String s = is.next();
if (s.equals("A"))
is.remove();
}
System.out.println(ls); // [B B]
…
Programmiermethodik - Java Collections
27
Beispiel (Iterator, Map)
import
import
import
import
java.util.HashMap;
java.util.Iterator;
java.util.Map;
java.util.Set;
public final class CollectionTest3 {
private CollectionTest3() {
}
}
public static void main(final String[] args) {
final Map<String, Double> m = new HashMap<String, Double>();
m.put("PC1", 1199.90);
Iterator über die Menge
m.put("PC2", 1999.90);
m.put("PC3", 980.00);
der Einträge
System.out.println(m);
final Set<Map.Entry<String, Double>> mes = m.entrySet();
final Iterator<Map.Entry<String, Double>> imes = mes.iterator();
while (imes.hasNext()) {
final Map.Entry<String, Double> item = imes.next();
if (item.getValue() > 1000) {
System.out.println(item.getKey());
}
}
Ausgabe:
}
{PC3=980.0, PC1=1199.9, PC2=1999.9}
Programmiermethodik - Java Collections
PC1
PC2
28
Listen-Iteratoren
• Für Listen gibt es noch eigene Iteratoren.

Diese implementieren das Interface ListIterator<T>.
• Ein Listen-Iterator kann sich vorwärts und rückwärts
bewegen.
• Zusätzlich zu den Methoden eines Iterators werden zum
Beispiel angeboten:
previous und hasPrevious, die sich auf das vorhergehende
Element beziehen.
 previousIndex und nextIndex liefern die Indexwerte des
vorhergehenden und nächsten Elements.

• Ein Listen-Iterator ist nicht verbraucht, wenn er am Ende der
Liste angekommen ist.
Programmiermethodik - Java Collections
29
Modifikation und Iteratoren (1)
• Wird eine Collection modifiziert (z.B. neues Element
einfügen), dann werden alle Iteratoren ungültig.
• Beim nächsten Zugriffsversuch auf einen Iterator nach einer
Änderung wirft dieser eine
ConcurrentModificationException.
• Wird als fail-fast bezeichnet.


Iterator gerät nicht irgendwann in einen inkonsistenten Zustand.
Iterator wird sofort unbrauchbar gemacht.
• Iteratoren reagieren nur auf strukturelle Änderungen, d.h.
Ersetzen eines Elements verändert die Struktur nicht und
lässt Iteratoren intakt.
Programmiermethodik - Java Collections
30
Modifikation und Iteratoren (2)
• Iteratoren bieten selbst Änderungsoperationen an, bei denen
der betreffende Iterator funktionsfähig bleibt.
• Alle Iteratoren definieren die Methode remove, die das
zuletzt überquerte Element aus der Collection entfernt.
• Aber
Iterator muss sich zuerst bewegen, dann erst kann remove
aufgerufen werden (löscht das letzte Element, das zurückgegeben
wurde).
 Nach einem Aufruf muss erst wieder ein Element überquert werden.
 Bei Listen-Iteratoren ist das zuletzt überquerte Element abhängig von
der Laufrichtung (kann vom Listenanfang aus gesehen vor oder hinter
dem Iterator sein).

Programmiermethodik - Java Collections
31
Modifikation und Iteratoren (3)
• Bei Listen-Iteratoren gibt es neben remove noch zusätzliche
Methoden.


add – fügt das Element in der Lücke ein, in der der Iterator steht.
set – ersetzt das zuletzt überquerte Element durch das übergebene
Element.
• Bei Änderungen über einen Iterator bleibt nur dieser eine
Iterator intakt.
• Andere Iteratoren, die in der gleichen Collection unterwegs
sind, werden ungültig (bei set bleiben alle intakt – keine
Strukturänderung).
Programmiermethodik - Java Collections
32
foreach - Schleife
• So wie Arrays können auch Collections mit der foreachSchleife durchlaufen werden.
• Beispiel
List<Integer> cl = new ArrayList<Integer>();
…
for (Integer in : cl)
System.out.println(in);
• Die foreach-Schleife unterliegt den gleichen
Beschränkungen wie bei Arrays.
• foreach-Schleifen arbeiten wie Iteratoren.
Eine Änderung der Collection während des Durchlaufens führt zu
einer Ausnahme.
 Implementiert eine Klasse das Interface Iterable<T>, dann können
Objekte dieser Klasse mit einer foreach-Schleife durchlaufen werden.

Programmiermethodik - Java Collections
33
Wichtige Themen
Abstrakte Collection-Klassen
• Unterstützen die Entwicklung neuer Collection-Klassen.
• Abstrakte Klassen implementieren schon einen großen Teil
eines Interfaces und lassen bestimmte Teile noch offen.
• Eine neue Collection-Klasse kann daher schon auf eine
abstrakte Klasse aufbauen (muss nicht alle Methoden eines
Interfaces implementieren).
• Vorgehensweise bei der Implementierung einer neuen
Collection-Klasse:
Auswählen einer geeigneten abstrakten Klasse von der geerbt
wird.
2. Implementierung aller abstrakten Methoden.
3. Sollte die Collection modifizierbar sein, dann müssen auch einige
konkrete Methoden überschrieben werden (wird in der APIDokumentation der abstrakten Klasse beschrieben).
4. Testen der neuen Klasse (inklusive Performance).
Programmiermethodik - Java Collections
35
1.
Beispiele für abstrakte Klassen
• Beispiele






AbstractCollection
AbstractSet
AbstractList (basierend auf Array)
AbstractSequentialList (basierend auf verketteter Liste)
AbstractQueue
AbstractMap
• In der API-Dokumentation jeder abstrakten Klasse wird
genau beschrieben, wie man eine Klasse davon ableiten
muss.



Grundlegende Implementierung
Welche Methoden müssen implementiert werden.
Welche Methoden müssen überschrieben werden, wenn man
Modifikationen zulassen möchte.
Programmiermethodik - Java Collections
36
Algorithmen im Collection-Framework
• Das Collection-Framework bietet neben vielen vordefinierten
Containerklassen auch Algorithmen für die Verarbeitung von
Container-Klassen an.
• Diese Algorithmen werden als statische Methoden
(polymorphe Methoden) in der Hilfsklasse Collections
gesammelt.
• Algorithmen (Beispiele)

sort

binarySearch

max

shuffle
 Sortiert die Elemente einer generischen Liste nach aufsteigender Größe.
 Sucht ein Element in der sortierten Liste (Voraussetzung) und liefert einen Index
zurück, wenn das Element gefunden wurde (ansonsten eine negative Zahl).
 Liefert das größte Element einer Collection.
 Mischt die Elemente einer generischen Liste zufällig.
Programmiermethodik - Java Collections
37
Vergleiche
• Viele Methoden (z.B. sort, binarySearch) vergleichen
Elemente der Größe nach.
• Für beliebige Elementtypen ist aber nicht ohne weiters klar,
welches von zwei Objekten das „größere“ ist.


Klassen müssen das generische Interface Comparable<T>
implementieren.
Es muss die Vergleichsmethode compareTo implementiert werden,
mit dem Ergebnis
 > 0 wenn das Objekt größer als der Parameter ist,
 < 0 wenn das Objekt kleiner als der Parameter ist,
 0 wenn das Objekt und der Parameter gleich sind.
Programmiermethodik - Java Collections
38
Comparator
• Oft sollen Objekte nach verschiedenen Kriterien verglichen
werden.
• Daher sind viele Collection-Methoden mit einem zusätzlichen
Parameter, einem Comparator, überladen.


Erfüllt den gleichen Zweck.
Zum Vergleich wird aber das übergebene Comparator-Objekt
benutzt.
• Comparator<T> ist ein generisches Interface mit einer
Methode compare.

Methode akzeptiert zwei Objekte des Elementtyps und liefert ein intErgebnis für den Vergleich der zwei Objekte.
Programmiermethodik - Java Collections
39
Comparator-Beispiel
List<String> ss = new ArrayList<String>();
ss.add("Hans");
ss.add("Sepp");
ss.add("franz");
System.out.println(ss); // [Hans, Sepp, franz]
Collections.sort(ss);
System.out.println(ss); // [Hans, Sepp, franz]
Comparator<String> ignoreCaseComparator = new Comparator<String>() {
public int compare(String s1, String s2) {
return (s1.toLowerCase().compareTo(s2.toLowerCase()));
}
};
Collections.sort(ss, ignoreCaseComparator);
System.out.println(ss); //[franz, Hans, Sepp]
Programmiermethodik - Java Collections
40
Unveränderliche Collection-Klassen
• In vielen Fällen möchte man Container-Klassen zur Verfügung
stellen, die unveränderlich sind.
• Die Klasse Collections bietet einige statische Methoden,
mit denen unveränderliche Sichten auf vorhandene
Container erzeugt werden können.



Sichten auf eine Datenstruktur kopieren eine zugrunde liegende
Datenstruktur nicht.
Bieten eine eingeschränkte Darstellung (z.B. Sperren aller
schreibenden Methoden).
Die Datenstruktur wird nicht verändert.
Programmiermethodik - Java Collections
41
Beispiel
• Methoden (Beispiele)
public static <T> List<T> unmodifiableList(List<? extends T> list)
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m)
public static <T> Set<T> unmodifiableSet(Set<? extends T> s)
• Anwendung
…
HashMap<String,Integer> m = new
HashMap<String,Integer>();
Map<String,Integer> rom =
Collections.unmodifiableMap(m);
m.put("TEST",1);
// rom.put("TEST",1);FEHLER!
…
Programmiermethodik - Java Collections
42
Übersicht (wichtige Klassen)
Typ
Ordnung bleibt
Null-Elemente
Duplikate
ArrayList
ja
ja
ja
LinkedList
ja
ja
ja
HashSet
nein
ja
nein
TreeSet
ja
nein
nein
HashMap
nein
ja
Schlüssel nein,
Werte ja
TreeMap
ja
Schlüssel nein,
Werte ja
Schlüssel nein,
Werte ja
Programmiermethodik - Java Collections
43
Herunterladen