Warum ConcurrentHashMap null Schlüssel und Werte verhindern?
-
22-08-2019 - |
Frage
Die JavaDoc von ConcurrentHashMap dies sagt:
Wie
Hashtable
aber im Gegensatz zuHashMap
diese Klasse tut nicht erlaubtnull
als Schlüssel oder Wert verwendet werden.
Meine Frage: Warum?
2. Frage: warum Hashtable nicht null zulassen
Ich habe eine Menge von HashMaps zum Speichern von Daten verwendet. Aber bei einem Wechsel ConcurrentHashMap ich wegen Nullpointerexceptions mehrmals in Schwierigkeiten geraten.
Lösung
Vom Autor von ConcurrentHashMap
selbst (Doug Lea) :
Der Hauptgrund, die NULL-Werte in ConcurrentMaps sind nicht erlaubt (ConcurrentHashMaps, ConcurrentSkipListMaps) ist, daß Mehrdeutigkeiten, die kann sein kann gerade noch erträglich in nicht-gleichzeitige Karten nicht gebracht. Die wichtigste davon ist, dass, wenn
map.get(key)
kehrtnull
, Sie kann nicht erkennen, ob explizit der Schlüssel zumnull
abbildet vs der Schlüssel nicht ist abgebildet. In einer nicht-gleichzeitigen Karte können Sie dies überprüfen, übermap.contains(key)
, aber in einer gleichzeitig ein, die Karte könnte sich geändert haben zwischen den Anrufen.
Andere Tipps
Ich glaube, es ist, zumindest teilweise, damit Sie containsKey
und get
in einen einzigen Aufruf kombinieren. Wenn die Karte nulls halten kann, gibt es keine Möglichkeit zu sagen, ob get
einen Null zurückkehrt, weil es kein Schlüssel für diesen Wert war, oder einfach nur, weil der Wert war null.
Warum ist das ein Problem? Denn es gibt keinen sicheren Weg, dass selbst zu tun. Nehmen Sie den folgenden Code ein:
if (m.containsKey(k)) {
return m.get(k);
} else {
throw new KeyNotPresentException();
}
Da m
eine gleichzeitige Karte ist, kann Schlüssel k zwischen den containsKey
und get
Anrufen gelöscht werden, so dass dieser Schnipsel ein Null zurückzugeben, die nie in der Tabelle war, anstatt die gewünschten KeyNotPresentException
.
Normalerweise würde man das lösen durch Synchronisieren, aber mit einer gleichzeitigen Karte, dass natürlich wird nicht funktionieren. Daher hatte die Signatur für get
zu ändern, und der einzige Weg, das zu tun, in einem rückwärtskompatiblen Art und Weise dem Benutzer das Einfügen von Nullwerten in erster Linie zu verhindern war, und weiterhin mit, dass als ein Platzhalter für „Schlüssel nicht gefunden“.
Josh Bloch entworfen HashMap
; Doug Lea entworfen ConcurrentHashMap
. Ich hoffe, dass nicht verleumderisch ist. Eigentlich denke ich, das Problem ist, dass NULL-Werte oft Verpackung erfordern, so dass die reale Null für nicht initialisierte stehen kann. Wenn Client-Code nulls erfordert dann kann es die (zugegebenermaßen klein) Kosten für die Verpackung nulls selbst zahlen.
ConcurrentHashMap ist Thread-sicher. Ich glaube, dass nicht erlaubt null Schlüssel und Werte waren ein Teil dafür zu sorgen, dass es Thread-sicher ist.
Ich denke, dass der folgende Ausschnitt aus der API-Dokumentation einen guten Hinweis gibt: „Diese Klasse ist vollständig kompatibel mit Hashtable in Programmen, die auf seiner Thread-Sicherheit verlassen, aber nicht auf seinen Synchronisation Details.“
Sie wollten wahrscheinlich nur ConcurrentHashMap
voll kompatibel / austauschbar Hashtable
machen. Und als Hashtable
erlaubt keine Null-Schlüssel und Werte ..
Sie können nicht auf einem Null synchronisieren.
Edit: Das ist nicht genau, warum in diesem Fall. Ich dachte zunächst, es war etwas Phantasie geht mit Dingen gegen gleichzeitige Aktualisierungen Sperren oder auf andere Weise den Objekt Monitor zu erkennen, ob etwas geändert, aber bei der Prüfung der Quellcode es scheint, ich falsch war - sie eine Sperre mit "Segment" basiert auf einer Bitmaske der Hash.
In diesem Fall ich vermute, sie haben es geschafft Hashtable zu kopieren, und ich vermute, Hashtable tat es, weil in der relationalen Datenbank Welt, null! = Null, so mit einem Null als Schlüssel keine Bedeutung hat.
Ich glaube nicht Nullwert nicht anzuerkennen ist eine richtige Option. In vielen Fällen wollen wir mit Nullwert in die con-aktuellen Karte eine Schlüssel do setzen. Jedoch durch ConcurrentHashMap verwenden, können wir das nicht tun. Ich schlage vor, dass die kommende Version von JDK kann man erkennen, unterstützen.