Das JavaDoc von ConcurrentHashMap
sagt dies:
Wie,
Hashtable
aber nicht, erlaubtHashMap
diese Klasse nicht ,null
als Schlüssel oder Wert verwendet zu werden.
Meine Frage: Warum?
2. Frage: Warum nicht Hashtable
null zulassen?
Ich habe viele HashMaps zum Speichern von Daten verwendet. Aber als ConcurrentHashMap
ich zu wechselte, bekam ich wegen NullPointerExceptions mehrmals Probleme.
java
concurrenthashmap
Marcel
quelle
quelle
Antworten:
Vom Autor seiner
ConcurrentHashMap
selbst (Doug Lea) :quelle
Optional
s als interne Werte verwendenOptional
ist eine Java 8-Funktion, die damals noch nicht verfügbar war (Java 5). Sie könntenOptional
jetzt tatsächlich s verwenden.Ich glaube , es ist zumindest teilweise zu erlauben , Sie zu kombinieren
containsKey
undget
zu einem einzigen Anruf. Wenn die Map Nullen enthalten kann, kann nicht festgestellt werden, obget
eine Null zurückgegeben wird, weil für diesen Wert kein Schlüssel vorhanden war oder nur weil der Wert null war.Warum ist das ein Problem? Weil es keinen sicheren Weg gibt, das selbst zu tun. Nehmen Sie den folgenden Code:
Da
m
es sich um eine gleichzeitige Zuordnung handelt, kann der Schlüssel k zwischen den AufrufencontainsKey
und gelöscht werdenget
, wodurch dieses Snippet eine Null zurückgibt, die nie in der Tabelle enthalten war, und nicht die gewünschteKeyNotPresentException
.Normalerweise würden Sie das durch Synchronisieren lösen, aber mit einer gleichzeitigen Karte funktioniert das natürlich nicht. Daher musste sich die Signatur für
get
ändern, und die einzige Möglichkeit, dies abwärtskompatibel zu tun, bestand darin, zu verhindern, dass der Benutzer überhaupt Nullwerte einfügt, und diese weiterhin als Platzhalter für "Schlüssel nicht gefunden" zu verwenden.quelle
map.getOrDefault(key, NULL_MARKER)
. Wenn janull
, war der Wertnull
. Wenn es zurückgegeben wirdNULL_MARKER
, war der Wert nicht vorhanden.Josh Bloch entworfen
HashMap
; Doug Lea entworfenConcurrentHashMap
. Ich hoffe das ist nicht verleumderisch. Eigentlich denke ich, dass das Problem darin besteht, dass Nullen oft umbrochen werden müssen, damit die echte Null für nicht initialisiert stehen kann. Wenn für den Client-Code Nullen erforderlich sind, kann er die (zugegebenermaßen geringen) Kosten für das Umschließen von Nullen selbst bezahlen.quelle
Sie können nicht mit einer Null synchronisieren.
Bearbeiten: Dies ist in diesem Fall nicht genau der Grund. Anfangs dachte ich, es wäre etwas Besonderes, Dinge gegen gleichzeitige Aktualisierungen zu sperren oder den Objektmonitor auf andere Weise zu verwenden, um festzustellen, ob etwas geändert wurde, aber bei der Prüfung des Quellcodes stellte sich heraus, dass ich falsch lag - sie sperren mit einem "Segment", das auf a basiert Bitmaske des Hash.
In diesem Fall vermute ich, dass sie es getan haben, um Hashtable zu kopieren, und ich vermute, dass Hashtable es getan hat, weil in der relationalen Datenbankwelt null! = Null ist, sodass die Verwendung einer Null als Schlüssel keine Bedeutung hat.
quelle
ConcurrentHashMap ist threadsicher. Ich glaube, dass das Nichtzulassen von Nullschlüsseln und -werten dazu beigetragen hat, sicherzustellen, dass es threadsicher ist.
quelle
Ich vermute, dass der folgende Ausschnitt der API-Dokumentation einen guten Hinweis gibt: "Diese Klasse ist in Programmen, die auf der Thread-Sicherheit, aber nicht auf den Synchronisationsdetails beruhen, vollständig mit Hashtable kompatibel."
Sie wollten wahrscheinlich nur
ConcurrentHashMap
voll kompatibel / austauschbar machenHashtable
. Und daHashtable
erlaubt keine Nullschlüssel und Werte ..quelle
Ich denke nicht, dass es eine richtige Option ist, den Nullwert nicht zuzulassen. In vielen Fällen möchten wir einen Schlüssel mit dem Wert Null in die aktuelle Karte einfügen. Mit ConcurrentHashMap können wir dies jedoch nicht tun. Ich schlage vor, dass die kommende Version von JDK dies unterstützen kann.
quelle