252-0027
Einführung in die Programmierung 9.0 Generische Programmierung
Thomas R. Gross
Übersicht
§ 9.4 Mengen
§ 9.5 Abbildungen
§ 9.6 Iteratoren
2
Java Collections Framework
<<Interface>
Collection
<<Interface>
List <<Interface>
Set
<<Interface>
SortedSet
<<Interface>
Map
<<Interface>
SortedMap
Mengen
§ Menge ("set"): Eine Sammlung eindeutiger und einzigartiger Elemente ( d.h., wir lassen keine Duplikate zu und können für 2
beliebige Elemente feststellen, ob sie gleich oder ungleich sind ) für die folgende Operationen ausgeführt werden können:
§ Hinzufügen (add), Entfernen (remove), Suche (contains)
§ Bei einer Menge erwarten wir keinen Zugriff über einen Index und eine Reihenfolge spielt keine Rolle
8
set.contains("to") true
set.contains("be") false
Menge (set)
"the" "of"
"from"
"to"
"she"
"you"
"him"
"why"
"in"
"by"
"down"
"if"
Set Implementierungen
§ In Java können Mengen durch Klassen, die das Set Interface (aus java.util) implementieren, dargestellt werden
§ Set wird durch die Klassen HashSet und TreeSet implementiert
10
Set Implementierungen
§ HashSet: Implementierung basiert auf einem "hash table" mit einem Array der schnelle Zugriffe erlaubt : O(1) für alle Operationen (mit bestimmten
Annahmen)
§ Elemente werden in irgendeiner (nicht bekannten) Reihenfolge gespeichert
§ TreeSet : Implementierung basiert auf einem "binären Baum";
Zugriff ist ziemlich schnell: O(log N) für alle Operationen
§ Elemente sind sortiert gespeichert
Beispiel
§ Thomas Mann, Die Buddenbrooks, 1'602'177 Bytes
§ Quelle: Projekt Guttenberg
§ Suche (1000 x, 18 Wörter)
§ Intel(R) Xeon(TM) CPU 2.40GHz
13Klasse Zeit (ms)
LinkedList 31520 ArrayList 8083
HashSet 2
TreeSet 10
Set Objekte
List<String> list = new ArrayList<String>();
...
Set<Integer> set1 = new TreeSet<Integer>(); // empty Set<String> set2 = new HashSet<String>(list);
§ Es gibt den Defaultkonstruktor (liefert die leere Menge)
und einen Konstrukor, der eine Menge basierend auf
einer anderen Collection erstellt.
15
Set Methoden
add(value) adds the given value to the set
contains(value) returns true if the given value is found in this set remove(value) removes the given value from the set
clear() removes all elements of the set isEmpty() returns true if the set's size is 0
toString() returns a string such as "[3, 42, -7, 15]"
19
Sets und Ordnungsrelationen
§ HashSet : Elemente sind in irgendeiner Reihenfolge gespeichert
Set<String> names = new HashSet<String>();
names.add("Jake");
names.add("Robert");
names.add("Marisa");
names.add("Kasey");
System.out.println(names);
// [Kasey, Robert, Jake, Marisa]
Sets und Ordnungsrelationen
§ TreeSet : Elemente werden gemäss compareTo Ordnung gespeichert
Set<String> names = new TreeSet<String>();
names.add("Jake");
names.add("Robert");
names.add("Marisa");
names.add("Kasey");
System.out.println(names);
// [Jake, Kasey, Marisa, Robert]
§ LinkedHashSet : in der Reihenfolge des Hinzufügens gespeichert
Set<String> names = new LinkedHashSet<String>();
...
// [Jake, Robert, Marisa, Kasey] 21
∀ Elemente der Menge
§ Da die Ordnung der Elemente in der Mengen nicht bekannt ist müssen wir einen (stabilen) Weg finden, Operationen mit allen Elemente einer Menge auszuführen.
§ Die Operation kann einen Test einschliessen der dann – je nach Ergebnis – die Operationen genauer definiert
§ Wenn element.hasProperty() dann element.moreOps()
§ Idee: Schleife über alle Elemente einer Menge
Die "for each" Schleife
Syntax:
for (type name : collection) { statements;
}
§ Definiert einen Loop über alle Elemente einer Ansammlung (z.B., Set , List – die Interface Collection implementieren) oder eines Arrays
23
Beispiel
Set<Double> scores = new HashSet<Double>();
scores.add(21.0);
scores.add(20.0);
scores.add(24.0);
scores.add(0.0);
//Double ist wrapper Typ!
for (double score : scores) {
System.out.println("The score is " + score);
}
Map<String, Double> staff = new HashMap<String, Double>();
staff.put("Peter", 1.0);
staff.put("Mary", 6.0);
Reihenfolge der Iteration
§ HashSet – nicht definiert.
§ LinkedHashSet – wie eingefügt.
§ ArrayList – wie eingefügt.
§ LinkedList – wie eingefügt.
§ TreeSet – aufsteigend (nach compareTo).
26
9.4 Abbildungen
Mengen (Sets) und Abbildungen (Maps)
§ Eine Menge ist eine Abbildung (map) der Elemente auf bool’sche Werte.
§ Set: Ist "ETH" in der Menge? (true/false)
§ Map: Was ist die Postleitzahl der "ETH"?
"ETH" Set true
false
"ETH" Map "8092"
30
Abbildungen ("Map")
§ Abbildung ("map"): Hält eine Menge Schlüssel (keys) und eine (An)Sammlung von Werten (values), wobei jeder
Schlüssel mit einem Wert assoziiert ist.
§ Auch als "dictionary", "associative array",
"hash" bekannt.
32
Einsatz von Abbildungen
§ Eine Abbildung stellt eine Assoziation zwischen Schlüssel und Werten her.
§ Speichert einen Wert für jeden Index (Schlüssel).
§ Später brauchen wir nur einen Schlüssel angeben und erhalten den entsprechenden Wert zurück:
Map // key value
put("ETH", "044-632-1111")
Abbildungen
§ Wichtigste Operationen:
§ put(key, value): Hinzufügen eines Schlüssels mit einem Wert
§ get(key): Lesen des Wertes der mit dem Schlüssel assoziiert ist.
§ remove(key): Entfernen des Schlüssels (und des mit ihm assoziierten Wertes)
34
Map Implementation
§ In Java, Abbildungen ("maps") werden durch Map Interface in java.util unterstützt .
§ Map wird durch die Klassen HashMap und TreeMap implementiert
§ HashMap: mit einem Array, dem "hash table", implementiert;
38
Map Methoden
put(key, value) adds a mapping from the given key to the given value;
if the key already exists, replaces its value with the given one get(key) returns the value mapped to the given key (null if not found) containsKey(key) returns true if the map contains a mapping for the given key remove(key) removes any existing mapping for the given key
clear() removes all key/value pairs from the map
size() returns the number of key/value pairs in the map isEmpty() returns true if the map's size is 0
Konstruktion von Abbildungen
Map<KeyType, ValueType> name = new TreeMap<KeyType,
ValueType>();
§ Könnte auch Referenzvariable
TreeMap<KeyType, ValueType> name deklarieren
§ Wollen vielleicht flexibel bleiben
41
keySet
§ Die Methode keySet liefert die Menge ( Set ) aller "Keys"
(Schlüssel) in der Abbildung (Map)
§ Kann die Menge aller Keys in einer for each Schleife bearbeiten
§ Kann den Wert, der zu einem Key gehört, durch Aufruf von get für die Map erhalten
Map<String, Integer> ages = new TreeMap<String, Integer>();
ages.put("Roland", 19);
ages.put("Clara", 2); // ages.keySet() returns Set<String>
43
Map Verhalten
§ Diese Abbildung (Map) speichert einen Wert (Integer) für einen Schlüssel (ein String, der "Name")
Map<String, Integer> ages = new TreeMap<String, Integer>();
ages.put("Roland", 19);
ages.put("Clara", 2);
ages.put("Sarah", 57);
ages.put("Clara", 3); // Clara had her birthday
for (String name : ages.keySet()) { // Clara -> 3
46
values
§ Die Methode values liefert eine Ansammlung aller in der Map auftretenden Werte
§ Kann diese Werte mit einer for each Schleife abarbeiten
§ Es gibt keinen einfachen Weg die Keys für einen Wert zu finden
Weitere Map Methoden
48
keySet() returns a set of all keys in the map
values() returns a collection of all values in the map
putAll(map) adds all key/value pairs from the given map to this map equals(map) returns true if given map has the same mappings as this
one
Umkehrfunktion der Abbildung
§ Es ist erlaubt, eine Map von Mengen, oder eine Liste von Listen, oder … zu definieren.
§ Wir wollen für jeden Assistenten seine Durchschnittsnote festhalten. Abbildung Name->Note
Map<String, Double> note = new HashMap<String, Double>();
note.put("Jared", 4.6);
50
System.out.println("Jared's Note ist " +
note.get("Jared")); // 4.6
§ Aber die Abbildung erlaubt es nicht, einfach nach all den Assistenten zu fragen, die eine bestimmte Note erreichten.
§ Was für eine Abbildung bräuchten wir dafür?
Umkehrabbildung
§ Wir können die Abbildung umkehren so dass es eine Abbildung von Noten auf Assistenten ist.
Map<
Double, String> note = new HashMap<
Double, String>();
note.put(4.6, "Jared");
note.put(5.0, "Alyssa");
note.put(5.9, "Steve");
note.put(4.6, "Stef");
note.put(4.0, "Rob");
...
System.out.println("Wer hatte eine 4.6? " + note.get(4.6)); // ???
52
§ Aber dieser Ansatz ist keine Lösung.
§ Wo ist das Problem?
§ Mehr als ein Assistant kann den selben Notendurchschnitt haben.
§ Die Map speichert nur den letzten Eintrag
55
Korrekte Umkehrabbildung
§ Jede Note muss auf eine Sammlung (Collection) von Assistenten abgebildet werden.
Map<Double, Set<String>> note =
new HashMap<Double, Set<String>>();
Korrekte Umkehrabbildung
Map<Double, Set<String>> note =
new HashMap<Double, Set<String>>();
note.put(4.6, new TreeSet<String>());
note.get(4.6).add("Jared");
note.put(5.0, new TreeSet<String>());
note.get(5.0).add("Alyssa");
note.put(5.9, new TreeSet<String>());
note.get(5.9).add("Steve");
note.get(4.6).add("Stef");
note.put(4.0, new TreeSet<String>());
note.get(4.0).add("Rob");
...
System.out.println("Wer hatte eine 4.6? " +
note.get(4.6)); // [Jared, Stef]
§ Wichtig ist dass die Menge initialisiert ist bevor das 1. Element
hinzugefügt wird.
58Übung
1. Schreiben Sie ein Programm, das zählt wieviele verschiedene Wörter in einem Text auftauchen.
§ Speichern Sie die Wörter in einer (An)Sammlung und halten Sie fest wie oft ein Wort in dem Text auftritt.
§ Nach dem Einlesen des Textes sollte es möglich sein, festzustellen wie oft ein bestimmtes Wort im Text auftritt.
2. Geben Sie jedes Wort das mindestens 1000mal auftritt aus
(sortiert nach der Häufigkeit (von 1000 an aufwärts)) und entfernen es aus der Menge.
61
Lösung der 1. Übungsaufgabe
// read file into a map of [word --> number of occurrences]
Map<String, Integer> wordCount = new HashMap<String, Integer>();
Scanner input = new Scanner(new File("mobydick.txt"));
while (input.hasNext()) {
String word = input.next();
if (wordCount.containsKey(word)) {
// seen this word before; increase count by 1 int count = wordCount.get(word);
wordCount.put(word, count + 1);
} else {
Scanner console = new Scanner(System.in);
System.out.print("Word to search for? ");
String word = console.next();
System.out.println("appears " + wordCount.get(word) +
" times.");
63
9.6 Iteratoren
Mit den Elementen einer Menge (Map) arbeiten
§ Auf die Elemente eines Java Set s oder einer Java Map kann nicht mit einem Index zugegriffen werden
§ Dafür gibt es den "for each" Loop:
Set<Double> scores = new HashSet<Double>();
for (double score : scores) {
System.out.println("The score is " + score);
}
65
Die "for each" Schleife
Syntax:
for (type name : collection) { statements;
}
§ Definiert einen Loop über alle Elemente einer Collection
(z.B., Set , List – die Interface Collection implementieren)
oder eines Arrays
67