08.05 Die Map-Schnittstelle
Bis jetzt haben Sie einfache Datenstrukturen kennengelernt. In diesem Kapitel lernen Sie die Schnittstelle java.util.Map kennen, die sich von den bisher vorgestellten Collections unterscheidet. In einer Map werden die darin gespeicherten Objekte nicht über einen Index (wie bei einer java.util.List) angesprochen, oder in beliebiger Reihenfolge (wie in einem Set) abgespeichert, sondern über einen Schlüssel (Key) identifiziert. Der Schlüssel stellt dabei ein Objekt einer (fast) beliebigen Klasse dar. Folglich kann einem Schlüssel auch nur ein Objekt (Wert, Value) zugeordnet werden. Die Schlüsselklasse sollte zudem die equals und hashCode Methoden korrekt überschreiben.
Allgemeines zu Maps
Zusätzlich zur klassischen Verwendung in Form von Schlüssel-Werte-Paaren einer Map, kann aus einer Map auch ein Set der Schlüssel, und eine Collection der enthaltenen Werte erzeugt werden. Die Reihenfolge, wie die Daten in einer Map liegen und zurückgegeben werden, ist nicht spezifiziert und wird im Zweifelsfall von der jeweiligen Implementierung festgelegt.
Generell sind Maps seit Java 5 generische Klassen. Es wird ein generischer Typ für den Schlüssel (Key), und ein generischer Typ für den Wert (Value) festgelegt.
Genauso wie bei Sets, muss auch bei den Keys einer Map bei der Verwendung von veränderbaren Objekten aufgepasst werden, da nicht festgelegt ist, wie sich eine Map verhält, wenn zwei bereits hinzugefügte Key-Objekte bei einer Veränderung gleich, also equals werden. Ein Beispiel:
public class EqualObject {
private String str;
public String getStr() {
return this.str;
}
public void setStr(String str) {
this.str = str;
}
public int hashCode() {
return this.str.hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof EqualObject) {
if (this.str != null) {
return this.str.equals(((EqualObject)obj).getStr());
}
}
return false;
}
}
EqualObject obj1 = new EqualObject();
obj1.setStr("Test");
EqualObject obj2 = new EqualObject();
obj2.setStr("Test2");
Map<EqualObject, String> map = new HashMap<EqualObject, String>();
map.put(obj1, "Ein String");
map.put(obj2, "Ein anderer String");
System.out.println(map.get(obj1)); // Ein String
System.out.println(map.get(obj2)); // Ein anderer String
obj2.setStr(obj1.getStr());
System.out.println(map.get(obj1)); // Ein String
System.out.println(map.get(obj2)); // Ein String
Auch darf eine Map sich nicht selbst als Key beinhalten.
Ebenso wie bei einer Collection, sollte auch eine Map mindestens zwei Konstruktoren bereitstellen. Einen leeren, der eine neue Map erzeugt, und einen, der als Übergabeparameter eine andere Map erhält, deren Inhalte auf diese Map übertragen werden sollen. Auch müssen nicht alle Methoden sinnvoll implementiert werden/sein. Es ist deshalb legitim, dass Methoden, die in der Dokumentation als optional gekennzeichnet sind (z. B. clear, put oder remove), nicht implementiert werden, sondern stattdessen beim Aufruf bspw. eine UnsupportedOperationException werfen.
Beachten Sie, dass nicht jede Map jedes Objekt als Key oder Value akzeptiert. Bspw. unterstützen nicht alle Maps einen null-Key. In solch einem Fall wird meistens eine NullPointerException oder eine ClassCastException geworfen.
Möchten Sie den zugeordneten Wert eines Schlüssels überschreiben, genügt es den Schlüssel mit dem neuen Wert einfach ein weiteres Mal zu setzen.
Methoden einer Map
- clear() – löscht alle Elemente aus der
Map(optional). - containsKey(Object key) – gibt
truezurück, wenn dieMapden entsprechenden Key enthält. - containsValue(Object value) – gibt
truezurück, wenn dieMapden entsprechenden Wert enthält. - entrySet() – gibt ein
Setder mappings dieserMapzurück. - get(Object key) – gibt das Objekt zurück, das mit dem übergebenen Schlüssel assoziiert wird.
- isEmpty() – gibt
truezurück, falls sich keine Einträge in derMapbefinden. - keySet() – gibt ein
Setmit allen Schlüsseln in dieserMapzurück. - put(K key, V value) – fügt ein Schlüssel-Werte-Paar der
Maphinzu (optional). - putAll(Map<? extends K, ? extends V> m) – fügt die Inhalte der übergebenen
MapdieserMaphinzu (optional). - remove(Object key) – entfernt den übergebenen Schlüssel mitsamt zugeordnetem Wert von der
Map(optional). - size() – gibt die Anzahl an Schlüssel-Werte-Paaren in der
Mapzurück. - values() – gibt eine
Collectionzurück, die alle Werte dieserMapenthält.
Verwendung
Eine Map wird immer dann eingesetzt, wenn mehrere Objekte jeweils einem anderen Objekt zugeordnet werden sollen. Dabei kann ein und das selbe Objekt mehreren Objekte-Schlüsseln zugeordnet werden, ein Schlüssel aber nur genau einem Werte-Objekt. Implementierungen der Map lernen Sie im Kapitel 08.08 Implementierungen von Map kennen. An dieser Stelle werfen wir aber noch einen kurzen Blick auf die java.util.HashMap, die in unserem Fall Benutzereigenschaften speichert:
// Map anlegen und befüllen
Map<String, String> properties = new HashMap<String, String>();
properties.put("firstname", "stefan");
properties.put("lastname", "Kiesel");
properties.put("birthday", "14.12.1987");
properties.put("birthplace", "Würzburg");
// Map ausgeben
for (String str : properties.keySet()) {
oSystem.out.println(str + ": " + properties.get(str));
}
// Werte verändern
properties.put("firstname", "Stefan");
// Gezielt auf einen Wert zugreifen
System.out.println("Hallo " + properties.get("firstname") + "!");