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
true
zurück, wenn dieMap
den entsprechenden Key enthält. - containsValue(Object value) – gibt
true
zurück, wenn dieMap
den entsprechenden Wert enthält. - entrySet() – gibt ein
Set
der mappings dieserMap
zurück. - get(Object key) – gibt das Objekt zurück, das mit dem übergebenen Schlüssel assoziiert wird.
- isEmpty() – gibt
true
zurück, falls sich keine Einträge in derMap
befinden. - keySet() – gibt ein
Set
mit allen Schlüsseln in dieserMap
zurück. - put(K key, V value) – fügt ein Schlüssel-Werte-Paar der
Map
hinzu (optional). - putAll(Map<? extends K, ? extends V> m) – fügt die Inhalte der übergebenen
Map
dieserMap
hinzu (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
Map
zurück. - values() – gibt eine
Collection
zurück, die alle Werte dieserMap
enthä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()) { System.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") + "!");