Die Java Map-Schnittstelle ist Teil des Java Collection-Frameworks, aber kein Untertyp der Collection-Schnittstelle. Daher verhält es sich anders als beispielsweise Listen oder andere Sammlungsobjekte. Jedes Element von Map<Key, Value> stellt ein Schlüssel-Wert-Paar dar. Sowohl Schlüssel als auch Wert sind einige Objekte. Alle Schlüssel in einer bestimmten Karte sind eindeutig, Werte jedoch nicht, sodass sie dupliziert werden können. Sie können sich Map in Java wie eine Art Wörterbuch oder Online-Shop-Katalog vorstellen, in dem Sie jeden Artikel anhand seines eindeutigen Index finden können. Der Schlüssel ist eine eindeutige Kennung des Werts in einer Map. Beispielsweise ist Map<String, Item> String eine ID eines Artikels aus dem Online-Shop. Laut Dokumentation verfügt Map über die nächsten Subschnittstellen:
Bindungen ;
ConcurrentMap<K,V> ;
ConcurrentNavigableMap<K,V> ;
LogicalMessageContext ;
MessageContext ;
NavigableMap<K,V> ;
SOAPMessageContext ;
SortedMap<K,V> .
Und implementiert Klassen:
AbstractMap
Attribute
AuthProvider
ConcurrentHashMap
ConcurrentSkipListMap
EnumMap
HashMap
Hash-tabelle
IdentityHashMap
LinkedHashMap
PrinterStateReasons
Eigenschaften
Anbieter
RenderingHints
SimpleBindings
TabularDataSupport
TreeMap
UIDefaults
WeakHashMap
Java AbstractMap ist eine abstrakte Klasse, die den größten Teil der Map-Schnittstelle implementiert.
Java HashMap ist eine Datenstruktur zum Speichern von Schlüssel-Wert-Paaren mithilfe einer Hash-Tabelle.
Java TreeMap ist eine Datenstruktur zur Verwendung eines Baumes, also zur Darstellung mit sortierten Schlüsseln.
WeakHashMap verwendet eine Hash-Tabelle mit schwachen Schlüsseln und zeigt Werte an, die vom Garbage Collector gelöscht werden können, wenn sie nicht mehr verwendet werden.
LinkedHashMap ist eine Karte mit der Reihenfolge des Hinzufügens von Elementen und ermöglicht die Iteration in der Einfügereihenfolge.
EnumMap erweitert die AbstractMap- Klasse für die Verwendung mit Enum-Schlüsseln.
IdentityHashMap verwendet beim Vergleichen von Dokumenten eine referenzielle Äquivalenzprüfung und ordnet die verglichenen Schlüssel mithilfe der Operation
== anstelle der Methode
equal() zu
Hier interessieren uns die beliebtesten Implementierungen von Map Interface: HashMap, TreeMap und LinkedHashMap. Die Reihenfolge der Kartenelemente hängt übrigens von bestimmten Implementierungen ab. Angenommen, TreeMap und LinkedHashMap haben eine vorhersehbare Reihenfolge der Elemente, HashMap hingegen nicht.
Kartenmethoden
Die Hauptoperationen jeder Map sind das Einfügen, Entfernen und Suchen von Elementen.
public Object put(Object key, Object value) fügt ein Element in die Karte ein.
public void putAll(Map map) fügt die angegebene Karte in die Karte ein.
public Object remove(Object key) löscht einen Eintrag entsprechend dem angegebenen Schlüssel.
public Object get(Object key) gibt den Wert für den angegebenen Schlüssel zurück.
public boolean containsKey(Object key) sucht den angegebenen Schlüssel aus dieser Map
public Set keySet() gibt eine Set-Ansicht zurück, die alle Schlüssel enthält
public Set enterSet() gibt eine Set-Ansicht mit allen Schlüsseln und Werten zurück.
Was ist HashMap?
Was ist HashMap? Es ist die beliebteste Implementierung der Map<Key,Value>-Schnittstelle. Diese Datenstruktur basiert auf dem Hashing-Prinzip.
Das Hauptprinzip der HashMap-Arbeit: Hashing
Um zu verstehen, was eine Hashmap ist und wie sie funktioniert, sprechen wir zunächst über Hashing und Hash-Funktionen. Eine Hash-Funktion ist nur eine Funktion im mathematischen Sinne. Es gibt also einen Eingabewert (ein Objekt, ein Datenelement) und die Funktion wandelt ihn mithilfe einer geeigneten Regel in einen Ausgabewert um – einen Hash. Ziemlich oft ist ein Hash eine hexadezimale Zahl mit der richtigen Länge. Die Regeln für Konvertierungsprozesse können unterschiedlich sein, sie unterliegen jedoch den folgenden Grundsätzen:
Eine bestimmte Eingabe (Objekt) hat einen bestimmten Hash-Code.
Wenn zwei Objekte gleich sind, sind auch ihre Hash-Codes gleich. Das Gegenteil ist nicht der Fall.
Wenn die Hash-Codes unterschiedlich sind, sind die Objekte definitiv nicht gleich.
Manchmal können verschiedene Objekte denselben Hash-Code haben. Es handelt sich um ein sehr unwahrscheinliches Ereignis namens „Kollision“, und eine qualitativ hochwertige Hash-Funktion sollte die Wahrscheinlichkeit von Kollisionen minimieren.
In Java hat jedes Objekt einen Hash-Code. Es wird von der hashCode-Methode der Object-Klasse berechnet, der übergeordneten Klasse aller Java-Objekte. Normalerweise überschreiben Entwickler diese Methode für ihre eigenen Klassen sowie die damit verbundenen Equals- Methoden.
HashMap: wie es funktioniert
Daher besteht die Klasse HashMap<K,V> wie jede Map-Implementierung aus Schlüsseln und Werten. Es speichert Schlüssel mithilfe von Hashing-Prinzipien. Innerhalb der HashMap werden Schlüssel-Wert-Paare in „Buckets“ gespeichert. Diese Buckets bilden zusammen eine „Tabelle“, ein internes Array verknüpfter Listen, und ihre Anfangsgröße beträgt 16. HashMap in Java verwendet den Hashcode des Schlüssels, um einen Bucket zu bestimmen, dem das Schlüssel/Wert-Paar zugeordnet werden soll: Die knifflige Funktion von HashMap besteht darin, dass jede Zelle (Bucket) der Tabelle [] nicht nur ein Paar, sondern mehrere enthält. Sie werden nicht als explizites Objekt (wie LinkedList), sondern als implizite Kette gespeichert. Die Kette entsteht dadurch, dass jedes Paar eine Verbindung zum nächsten Paar speichert. Das heißt, alle HashMap-Paare sind über 16 Ketten verteilt. Wenn Sie ein neues Paar in die Tabelle einfügen, wird der Hash des Schlüssels berücksichtigt. Dieser Hash ist keine in das Schlüsselobjekt integrierte Hashcode-Funktion. Es wird davon ausgegangen, dass er im Bereich von 0-15 liegt. Das Paar wird der im Bucket gespeicherten Paarkette mit dem Hash-Index hinzugefügt. Dieser Ansatz beschleunigt die Suche. Bei der Suche nach einem Paar anhand des Schlüssels ist es nicht erforderlich, die gesamte Tabelle durchzugehen. Der Hash des Schlüssels wird berücksichtigt und nur die Kette überprüft, die in der Zelle mit dem Hash-Index gespeichert ist. Wenn die HashMap zu viele Paare enthält, werden die Ketten zu lang. Dann nimmt die Größe des Arrays zu, der Hash aller gespeicherten Objekte wird neu berechnet und sie werden entlang neuer Ketten verteilt.
HashMap-Deklaration
Wenn Sie zum HashMap-Code der Klasse gehen, finden Sie die nächste Deklaration:
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable
Dabei ist K der Typ der von dieser Zuordnung verwalteten Schlüssel und V der Typ der zugeordneten Werte. Dies ist ein Beispiel für eine HashMap-Deklaration mit Integer-Schlüssel und String-Wert in Ihrem Code:
HashMap<Integer, String> myHashMap = new HashMap<Integer, String>();
HashMap-Methoden
Hier ist die Liste der HashMap-Methoden.
Object get(Object key) gibt den Wert für den angegebenen Schlüssel zurück;
Das Objekt put(Key k, Value v) fügt die Schlüsselwertzuordnung in die Karte ein;
Objekt entfernen(Objektschlüssel) entfernt die Zuordnung für den angegebenen Schlüssel aus dieser Zuordnung, falls vorhanden;
void clear() entfernt alle Schlüssel-Wert-Paare aus der HashMap;
Object clone() gibt eine flache Kopie dieser HashMap-Instanz zurück, ohne die Schlüssel und Werte zu klonen;
boolean containsKey(Object key) gibt „true“ zurück, wenn der angegebene Schlüssel in der Karte gefunden wird, andernfalls „false“;
boolean enthältValue(Objektwert) gibt „true“ zurück, wenn der angegebene Schlüssel in der Karte gefunden wird, andernfalls „false“;
boolean isEmpty() gibt „true“ zurück, wenn die Karte leer ist, andernfalls „false“;
Set keySet() gibt den Satz der aus der Karte abgerufenen Schlüssel zurück;
int size() gibt die Menge der Schlüsselwertzuordnung zurück;
Collection Values() gibt eine Sammlung der Werte der Karte zurück;
Objekt entfernen(Objektschlüssel) entfernt das Schlüssel-Wert-Paar für den angegebenen Schlüssel;
void putAll(Map m) kopiert alle Elemente der Karte in die andere Karte.
Java HashMap-Beispiel
Lassen Sie uns ein Beispielprogramm mit Java HashMap erstellen, um zu demonstrieren, wie es funktioniert:
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Set;
public class HashMap {
public static void main(String[] args) {
{
// HashMap declaration
HashMap<Integer, String> myHashMap = new HashMap<Integer, String>();
//Adding elements into HashMap
myHashMap.put(7, "Johnny");
myHashMap.put(8, "Ivy");
myHashMap.put(1, "Rick");
myHashMap.put(4, "Stan");
myHashMap.put(3, "Kyle");
//print out the map content using Iterator
Set set = myHashMap.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) iterator.next();
System.out.print("key: " + mapEntry.getKey() + " value: ");
System.out.println(mapEntry.getValue());
}
System.out.println("get an element from myHashMap via key and print the value out:");
System.out.println(myHashMap.get(8));
//print out hashMap on standard way:
System.out.println(myHashMap);
// Get values based on key
String var = myHashMap.get(2);
//here we'll get null, we don't have such a key
System.out.println("Value with key 2: " + var);
var = myHashMap.get(7);
System.out.println("Value with key 7: " + var);
// Remove values based on key
myHashMap.remove(4);
System.out.println("myHashMap after removing element:");
System.out.println(myHashMap);
myHashMap.clear();
System.out.println("myHashMap after total clearing:");
System.out.println(myHashMap);
}
}
}
Das Ergebnis der Ausführung des Programms:
key: 1 value: Rick
key: 3 value: Kyle
key: 4 value: Stan
key: 7 value: Johnny
key: 8 value: Ivy
get an element from myHashMap via key and print the value out:
Ivy
{1=Rick, 3=Kyle, 4=Stan, 7=Johnny, 8=Ivy}
Value with key 2: null
Value with key 7: Johnny
myHashMap after removing element:
{1=Rick, 3=Kyle, 7=Johnny, 8=Ivy}
myHashMap after total clearing:
{}
TreeMap
TreeMap in Java implementiert auch die Map<Key,Value>-Schnittstelle, basiert jedoch auf der Rot-Schwarz-Baumdatenstruktur. Ein Baum besteht aus „Knoten“ und Linien, die Knoten verbinden – Zweige. Der „Wurzel“-Knoten befindet sich an der Spitze des Baums. Von der Wurzel aus können Zweige und Knoten vorhanden sein. Es handelt sich um eine hierarchische Struktur, wie Sie sich vorstellen können diese Knoten als „Kinder“ der Wurzel. Untergeordnete Knoten können ihre eigenen untergeordneten Knoten haben – niedrigere Knoten. Knoten ohne untergeordnete Knoten werden „Endknoten“ oder „Blätter“ genannt. Ein binärer Baum ist ein Baum, in dem jeder Knoten null und eins hat oder zwei Kinder. Der binäre Suchbaum ist eine Struktur, in der jeder interne Knoten einen Schlüssel und manchmal einen zugehörigen Wert speichert und über zwei unterschiedliche Unterbäume („links“ und „rechts“) verfügt. Ein selbstausgleichender binärer Suchbaum ist ein knotenbasierter binärer Suchbaum, der seine Höhe (maximale Anzahl von Ebenen unterhalb der Wurzel) automatisch klein hält, wenn willkürliche Elemente eingefügt und gelöscht werden. Ein Rot-Schwarz-Baum ist ein ausgeglichener Binärbaum mit den Eigenschaften:
Jeder Knoten ist entweder rot oder schwarz
Die Wurzel ist immer schwarz
Jedes Blatt ist ein NIL-Knoten (sozusagen leer, null) und schwarz
Wenn ein Knoten rot ist, sind seine untergeordneten Knoten definitiv schwarz.
Jeder einfache Pfad von einem Knoten zu einem untergeordneten Blatt enthält die gleiche Anzahl schwarzer Knoten.
Eine TreeMap-Funktion
Eine TreeMap verwendet eine Baumdatenstruktur, um die Schlüssel als Knoten zu speichern und sortiert die Schlüssel mithilfe des Rot-Schwarz-Baum-Algorithmus. Deshalb sortiert TreeMap seine Einträge entsprechend der natürlichen Reihenfolge seiner Schlüssel. Für Zahlen ist die natürliche aufsteigende Reihenfolge, für Zeichenfolgen die alphabetische Reihenfolge. Sie können einen Komparator verwenden, wenn Sie die Bestelllogik ändern müssen. Ein großer Vorteil von TreeMap ist das natürliche Sortieren von Objekten sowie das Auffinden einiger Objekte mithilfe unterschiedlicher Filter und Bedingungen.
TreeMap-Methoden
Object get(Object key) gibt den Wert des entsprechenden Schlüssels zurück;
Object put(Object key, Object value) fügt eine Zuordnung in eine Zuordnung ein;
Objekt entfernen(Objektschlüssel) entfernt die Zuordnung für diesen Schlüssel, wenn die TreeMap ihn enthält;
boolean containsKey(Object key) gibt true zurück, wenn diese Map eine Zuordnung für den angegebenen Schlüssel enthält;
boolean enthältValue(Objektwert) gibt „true“ zurück, wenn die TreeMap einen oder mehrere Schlüssel dem angegebenen Wert zuordnet;
Das Objekt firstKey() gibt den ersten Schlüssel zurück, der sich derzeit in der sortierten Karte befindet.
Das Objekt lastKey() gibt den letzten Schlüssel zurück, der sich derzeit in der sortierten Karte befindet.
void putAll(Map map) kopiert alle Zuordnungen von der angegebenen Karte auf die Karte;
Set enterSet() gibt eine Set-Ansicht der Zuordnungen zurück
int size() gibt die Anzahl der Schlüssel-Wert-Zuordnungen zurück
Collection Values() gibt eine Sammlungsansicht der Werte zurück
Object clone() gibt eine flache Kopie der TreeMap zurück
void clear() entfernt alle Zuordnungen aus der TreeMap
SortedMap headMap(Object key_value) gibt eine Ansicht des Teils der Karte zurück, der kleiner als der Parameter key_value ist
Set keySet() gibt eine Set-Ansicht der in der Treemap enthaltenen Schlüssel zurück
SortedMap subMap(K fromKey, K toKey) gibt eine Ansicht des Teils dieser Karte zurück, dessen Schlüssel von fromKey (einschließlich) bis toKey (exklusiv) reichen
Das Objekt firstKey() gibt den ersten Schlüssel aus der TreeMap zurück.
TreeMap-Beispiel
import java.util.TreeMap;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
public class TreeMapExample {
public static void main(String args[]) {
//TreeMap declaration
TreeMap<Integer, String> myTreeMap = new TreeMap<Integer, String>();
//put elements to TreeMap
myTreeMap.put(1, "Stuart");
myTreeMap.put(23, "Michael");
myTreeMap.put(7, "Johnny");
myTreeMap.put(5, "Ivy");
myTreeMap.put(2, "Alex");
//Display and print out myTreeMap using Iterator
Set set = myTreeMap.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry myEntry = (Map.Entry) iterator.next();
System.out.print("key: " + myEntry.getKey() + " value: ");
System.out.println(myEntry.getValue());
}
//TreeMap printed in classical way
System.out.println(myTreeMap);
//removing an element with the key =2
myTreeMap.remove(2);
//myTreeMap after removing:
System.out.println(myTreeMap);
}
}
Das Ergebnis der Ausführung des Programms:
key: 1 value: Stuart
key: 2 value: Alex
key: 5 value: Ivy
key: 7 value: Johnny
key: 23 value: Michael
{1=Stuart, 2=Alex, 5=Ivy, 7=Johnny, 23=Michael}
{1=Stuart, 5=Ivy, 7=Johnny, 23=Michael}
LinkedHashMap
LinkedHashMap ist eine Datenstruktur, die verknüpfte Listen und Hash-Maps kombiniert. Tatsächlich erweitert LinkedHashMap die HashMap-Klasse und implementiert die Map-Schnittstelle, aber was hat es mit verknüpften Listen auf sich? Die Deklaration von LinkedHashMap:
Map <Integer, String> linkedHashMap = new LinkedHashMap <Integer, String>();
Diese neue LinkedHashMap erbt Eigenschaften von HashMap (wie Tabelle, LoadFactor, Schwellenwert, Größe, EntrySet) und erhält außerdem zwei spezielle Eigenschaften:
header ist der Kopf einer doppelt verknüpften Liste. Während der Initialisierung zeigt es sich an
accessOrder gibt an, wie man mithilfe des Iterators Zugriff auf Elemente erhält. Wenn wahr, in der Reihenfolge des letzten Zugriffs. Bei „false“ erfolgt der Zugriff in der Reihenfolge, in der die Elemente eingefügt wurden.
Diese verknüpfte Liste definiert die Iterationsreihenfolge. Normalerweise ist es die Reihenfolge, in der Schlüssel in die Karte eingefügt werden.
LinkedHashMap-Methoden
Object get(Object key) gibt den Wert zurück, dem der angegebene Schlüssel zugeordnet ist, oder null, wenn diese Zuordnung keine Zuordnung für den Schlüssel enthält
void clear() entfernt alle Zuordnungen aus der Karte.
boolean containsKey(Object key) gibt true zurück, wenn das angegebene Element durch einen oder mehrere Schlüssel zugeordnet ist
boolean removeEldestEntry(Map.Entry eldest) gibt true zurück, wenn die Karte ihren ältesten Eintrag aus der Karte entfernt
Set<Map.Entry<K,V>> enterSet() gibt eine Set-Ansicht der in dieser Karte enthaltenen Zuordnungen zurück
void forEach(BiConsumer<? super K,? super V> action) führt die angegebene Aktion für jeden Eintrag in dieser Karte aus, bis alle Einträge verarbeitet wurden oder die Aktion eine Ausnahme auslöst.
Das Objekt getOrDefault(Object key, V defaultValue) gibt den Wert zurück, dem der angegebene Schlüssel zugeordnet ist. Wenn die Karte keine Zuordnung für den Schlüssel enthält, wird defaultValue zurückgegeben.
Set<K> keySet() gibt eine Set-Ansicht der in der Karte enthaltenen Schlüssel zurück
boolean removeEldestEntry(Map.Entry<K,V> eldest) gibt true zurück, wenn diese Karte ihren ältesten Eintrag entfernen soll
void replaceAll(BiFunction<? super K,? super V,? erweitert V> function) ersetzt jeden Eintragswert durch das Ergebnis des Aufrufs der angegebenen Funktion für diesen Eintrag, bis alle Einträge verarbeitet wurden oder die Funktion eine Ausnahme auslöst.
Collection<v>values() gibt eine Sammlungsansicht der in der Karte enthaltenen Werte zurück
LinkedHashMap-Beispiel
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
public class HashLinkedListExample {
public static void main(String args[]) {
// LinkedHashMap Declaration
LinkedHashMap<Integer, String> myLinkedHashMap =
new LinkedHashMap<Integer, String>();
//Adding elements into LinkedHashMap
myLinkedHashMap.put(7, "Johnny");
myLinkedHashMap.put(12, "Rick");
myLinkedHashMap.put(1, "Kyle");
myLinkedHashMap.put(5, "Percy");
myLinkedHashMap.put(85, "Sebastian");
// Generate a Set of entries
Set set = myLinkedHashMap.entrySet();
// Display and print out the nodes of LinkedHashMap
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.print("key: "+ me.getKey() +
" value: "+me.getValue()+"\n");
}
//print out HashLinkedMap on standard way:
System.out.println(myLinkedHashMap);
myLinkedHashMap.put(21, "Ivy");
System.out.println(myLinkedHashMap);
myLinkedHashMap.remove(12);
System.out.println(myLinkedHashMap);
myLinkedHashMap.put(12, "Ronny");
System.out.println(myLinkedHashMap);
myLinkedHashMap.put(1, "Stan");
System.out.println(myLinkedHashMap);
}
}
Hier erstellen wir eine neue LinkedHashMap, fügen fünf Elemente hinzu und drucken sie dann mit einem Iterator und auf klassische Weise aus. Wie Sie sehen, behält LinkedHashMap die Einfügereihenfolge bei. Danach löschen wir ein Element aus unserer Karte, fügen dann das neue hinzu und später ein weiteres Element mit dem Schlüssel, das sich bereits auf der Karte befindet. Es ersetzt den alten Wert, der diesem Schlüssel zugeordnet ist. Das Ergebnis des laufenden Programms:
HashMap, TreeMap und LinkedHashMap sind die Implementierungen von Map-Schnittstellen. HashMap und LinkedHashMap sind Datenstrukturen, die Schlüssel hashen. TreeMap verwendet die natürliche Reihenfolge seiner Schlüssel zum Organisieren eines Suchbaums. Befehl:
HashMap behält keine Reihenfolge bei.
TreeMap sortiert die Einträge in aufsteigender Reihenfolge nach Schlüsseln.
LinkedHashMap behält die Einfügereihenfolge bei.
Nullschlüssel:
HashMap und LinkedHashMap ermöglichen einen Nullschlüssel.
LinkedHashMap lässt keine Nullschlüssel zu, wenn die Schlüssel eine natürliche Reihenfolge verwenden oder Comparator den Vergleich auf Null-Leys nicht unterstützt.
Lassen Sie uns ein Java-Map-Beispiel haben, das alle drei in diesem Artikel besprochenen Implementierungen enthält:
Wie wir sehen können, ist die Reihenfolge der Elemente in HashMap nicht offensichtlich, in TreeMap hängt sie von Schlüsseln ab, in LinkedHashMap kommt es auf die Einfügereihenfolge an. Wenn wir versuchen, einen Nullschlüssel in LinkedIn zu platzieren, erhalten wir eine NullPointerException, aber in LinkedIn, wo die Schlüssel Strings sind, können wir dies tun. Eine Hash-Map ist die beste Kartenimplementierung für allgemeine Zwecke. Es bietet maximale Suchgeschwindigkeit, schnelle Speicher- und Abrufvorgänge, Sie sollten jedoch an die chaotische Reihenfolge denken. Eine verknüpfte Hash-Map erbt die Vorteile von HashMap und erhält eine Reihenfolge für die Schlüssel. Es enthält jedoch eine verknüpfte Liste, die in Bezug auf den Speicher relativ kostspielig ist. Es ist langsamer als HashMap bei der Suche und etwas langsamer beim Hinzufügen/Entfernen, da eine verknüpfte Liste verwaltet wird. Eine Baumkarte speichert Schlüssel in aufsteigender Reihenfolge sortiert. Jedoch,
Um das Gelernte zu vertiefen, empfehlen wir Ihnen, sich eine Videolektion aus unserem Java-Kurs anzusehen
Java Developer bei Toshiba Global Commerce Solutions
Before IT, Alexandr managed to work in various fields and companies: at Guinness World Records, London Olympics 2021, and Nielsen, ...
[Vollständige Biografie lesen]
GO TO FULL VERSION