Denken Sie daran, dass es sich bei einer Map um strukturierte Daten handelt, die aus einer Reihe von Schlüssel-Wert-Paaren bestehen, und dass jeder Schlüssel nur einmal in einer einzelnen Map verwendet werden kann. Dieses Thema behandelt 9 grundlegende Fragen zur Verwendung von Map in Java und seinen implementierten Klassen. Der Einfachheit halber werde ich in den Beispielen Verallgemeinerungen verwenden . Daher werde ich einfach Map schreiben, ohne den Map-Bezeichner anzugeben. Sie können jedoch davon ausgehen, dass beide Werte von K und V vergleichbar sind, was bedeutet, dass K Comparable erweitert und V auch Comparable erweitert .
0. Konvertieren einer Karte in eine Liste
In Java bietet die Map- Schnittstelle drei Arten von Sammlungen: einen Schlüsselsatz, einen Wertesatz und einen Schlüsselwertsatz. Alle können mithilfe des Konstruktors oder der Methode in eine ListeaddAll()
umgewandelt werden . Der folgende Codeausschnitt zeigt, wie man aus einer Map eine ArrayList erstellt .
// Liste der Schlüssel
List keyList = new ArrayList(Map.keySet());
//Liste von Werten
List valueList = new ArrayList(Map.valueSet());
//Schlüsselwert auflisten
List entryList = new ArrayList(Map.entrySet());
1. Durchlaufen Sie alle Werte in der Karte
Das Durchgehen jedes Schlüssel-Wert-Paares ist das grundlegendste Verfahren zum Durchgehen einer Karte. In Java wird jedes Paar in einem Map-Feld namens Map.Entry gespeichert .Map.entrySet()
gibt eine Reihe von Schlüsselwerten zurück. Der effizienteste Weg, alle Werte einer Map zu durchlaufen, wäre also:
for(Entry entry: Map.entrySet()) {
//hol den Schlüssel
K key = entry.getKey();
//Wert erhalten
V value = entry.getValue();
}
Wir können auch verwenden Iterator
, insbesondere in Versionen, die jünger als JDK 1.5 sind
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
//hol den Schlüssel
K key = entry.getKey();
//Wert erhalten
V value = entry.getValue();
}
2. Ordnen der Karte nach Schlüsseln
Das Organisieren von Karten nach Schlüsseln ist ein weiteres häufig verwendetes Verfahren. Die erste Möglichkeit besteht darin, Map.Entry zur Liste hinzuzufügen und mit einem Komparator zu sortieren, der nach Werten sortiert.List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getKey().compareTo(e2.getKey());
}
});
Eine andere Möglichkeit: Verwenden Sie SortedMap , das zusätzlich auch seine Schlüssel in der richtigen Reihenfolge anordnet. Alle Schlüssel müssen jedoch Comparable verkörpern oder vom Komparator akzeptiert werden. Eine der implementierten Klassen SortedMap
ist TreeMap . Sein Konstruktor akzeptiert einen Komparator. Der folgende Code zeigt, wie man einen normalen Map
in einen geordneten umwandelt.
SortedMap sortedMap = new TreeMap(new Comparator() {
@Override
public int compare(K k1, K k2) {
return k1.compareTo(k2);
}
});
sortedMap.putAll(Map);
3. Ordnen Sie die Karte nach Werten
Das Hinzufügen einer Karte zur Liste und das anschließende Sortieren funktioniert in diesem Fall, aber dieses Mal müssen Sie verwendenEntry.getValue()
. Der folgende Code ist fast derselbe wie zuvor.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
SortedMap
Wir können es in diesem Fall immer noch verwenden , aber nur, wenn die Werte eindeutig sind. In diesem Fall können Sie das Schlüssel-Wert-Paar in einen Schlüsselwert umwandeln. Diese Lösung weist erhebliche Einschränkungen auf und wird von mir nicht empfohlen.
4. Initialisieren einer statischen/unveränderlichen Karte
Wenn Sie möchten, dass eine Map unveränderlich bleibt, ist es eine gute Möglichkeit, sie in eine unveränderliche Map zu kopieren. Mit dieser defensiven Programmiertechnik können Sie eine Map erstellen, die nicht nur sicher zu verwenden, sondern auch threadsicher ist. Um eine statische/unveränderliche Map zu initialisieren, können wir einen Initialisierer verwendenstatic
(siehe unten). Das Problem mit diesem Code besteht darin, dass Map zwar als deklariert ist static final
, wir aber beispielsweise nach der Initialisierung weiterhin damit arbeiten können Test.Map.put(3,"three");
. Es handelt sich also nicht um echte Unveränderlichkeit. Um eine unveränderliche Map mit einem statischen Initialisierer zu erstellen, benötigen wir eine superanonyme Klasse, die wir im letzten Initialisierungsschritt zur unveränderlichen Map hinzufügen. Bitte schauen Sie sich den zweiten Teil des Codes an. Wenn eine UnsupportedOperationException ausgelöst wird , wenn Sie ausführen Test.Map.put(3,"three");
.
public class Test {
private static final Map Map;
static {
Map = new HashMap();
Map.put(1, "one");
Map.put(2, "two");
}
}
public class Test {
private static final Map Map;
static {
Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
Map = Collections.unmodifiableMap(aMap);
}
}
Die Guava- Bibliothek unterstützt auch verschiedene Möglichkeiten zum Initialisieren statischer und unveränderlicher Sammlungen. Weitere Informationen zu den Vorteilen des Dienstprogramms für unveränderliche Sammlungen von Guava finden Sie im Abschnitt „Unveränderliche Sammlungen“ im Guava-How-to .
5. Unterschied zwischen HashMap, TreeMap und Hashtable
Es gibt drei Hauptimplementierungen der Map- Schnittstelle in Java: HashMap , TreeMap und Hashtable . Die Hauptunterschiede sind wie folgt:- Reihenfolge der Passage . HashMap und HashTable garantieren nicht die Reihenfolge der Map; Sie übernehmen insbesondere keine Gewähr dafür, dass die Bestellung im Laufe der Zeit gleich bleibt. Aber
TreeMap
es ordnet alle Werte in der „natürlichen Reihenfolge“ der Schlüssel oder durch einen Komparator. - Gültige Schlüssel-Wert-Paare.
HashMap
ermöglicht es Ihnen, einen Nullschlüssel und einen Nullwert zu haben.HashTable
erlaubt keinen Nullschlüssel oder Nullwert. WennTreeMap
die natürliche Reihenfolge verwendet wird oder der Komparator keinen Nullschlüssel zulässt, wird eine Ausnahme ausgelöst. - Synchronisierung . Nur
HashTable
synchronisiert, der Rest nicht. Wenn jedoch keine Thread-sichere Implementierung erforderlich ist, wird empfohlen,HashMap
stattdessen „ zu verwendenHashTable
.
. | HashMap | HashTable | TreeMap
-------------------------------------------------------
Упорядочивание |нет |нет | да
null в ключ-Bedeutung | да-да | нет-нет | нет-да
синхронизировано | нет | да | нет
производительность | O(1) | O(1) | O(log n)
воплощение | корзины | корзины | красно-чёрное дерево
Lesen Sie mehr über die Beziehung zwischen HashMap und HashMap . TreeMap vs. Hashtable vs. LinkedHashMap .
6. Karte mit umgekehrter Suche/Ansicht
Manchmal benötigen wir eine Reihe von Schlüssel-Schlüssel-Paaren, was bedeutet, dass die Werte genauso einzigartig sind wie die Schlüssel (ein Eins-zu-Eins-Muster). Diese Konsistenz ermöglicht es Ihnen, eine „invertierte Ansicht/Suche“ auf der Karte zu erstellen. Das heißt, wir können einen Schlüssel anhand seines Werts finden. Diese Datenstruktur wird als bidirektionale Map bezeichnet , was vom JDK leider nicht unterstützt wird. Sowohl Apache Common Collections als auch Guava bieten bidirektionale Kartenimplementierungen namens BidiMap bzw. BiMap. Beide führen eine Einschränkung ein, die eine 1:1-Zuordnung zwischen Schlüsseln und Werten erzwingt.7. Flache Kopie der Karte
Fast alle, wenn nicht alle Maps in Java enthalten einen Kopierkonstruktor für eine andere Map. Der Kopiervorgang ist jedoch nicht synchronisiert. Das heißt, wenn ein Thread eine Map kopiert, kann ein anderer Thread ihre Struktur ändern. Um eine plötzliche Desynchronisierung der Kopie zu verhindern, sollte in einem solchen Fall einer von ihnen verwendet werdenCollections.synchronizedMap()
.
Map copiedMap = Collections.synchronizedMap(Map);
Eine weitere interessante Möglichkeit zum flachen Kopieren ist die Verwendung von clone()
. Aber es wird NICHT einmal vom Erfinder des Java-Collections-Frameworks, Joshua Bloch, empfohlen. In der Debatte „ Copy Constructor vs. Cloning “ vertritt er den Standpunkt: Zitat: „Ich stelle oft eine öffentliche Klonmethode in konkreten Klassen bereit, weil die Leute erwarten, dass sie dort vorhanden sind. ... es ist eine Schande, dass das Klonen kaputt ist, aber es.“ ist passiert. ... Klonen ist eine Schwachstelle und ich denke, die Menschen sollten vor seinen Grenzen gewarnt werden.“ Aus diesem Grund zeige ich Ihnen nicht einmal, wie Sie die Methode clone()
zum Kopieren von Map verwenden
8. Erstellen Sie eine leere Karte
WennMap
unveränderlich, verwenden Sie:
Map = Collections.emptyMap();
Oder verwenden Sie eine andere Ausführungsform. Zum Beispiel:
Map = new HashMap();
ENDE
GO TO FULL VERSION