El JavaDoc de ConcurrentHashMap
dice esto:
Me gusta
Hashtable
peroHashMap
no me gusta , esta clase no permitenull
ser utilizada como clave o valor.
Mi pregunta: ¿por qué?
2da pregunta: ¿Por qué no Hashtable
permite nulo?
He usado muchos HashMaps para almacenar datos. Pero al cambiar a ConcurrentHashMap
Me metí en problemas varias veces debido a NullPointerExceptions.
java
concurrenthashmap
Marcel
fuente
fuente
Respuestas:
Del autor de
ConcurrentHashMap
sí mismo (Doug Lea) :fuente
Optional
s como valores internamenteOptional
es una característica de Java 8, que no estaba disponible en ese entonces (Java 5). Podrías usarOptional
s ahora, de hecho.Creo que es, al menos en parte, para que pueda combinar
containsKey
yget
en una sola llamada. Si el mapa puede contener nulos, no hay forma de saber siget
está devolviendo un valor nulo porque no había una clave para ese valor, o simplemente porque el valor era nulo.¿Por que eso es un problema? Porque no hay una forma segura de hacerlo tú mismo. Toma el siguiente código:
Como
m
es un mapa concurrente, la clave k puede eliminarse entre las llamadascontainsKey
yget
, lo que hace que este fragmento devuelva un valor nulo que nunca estuvo en la tabla, en lugar de lo deseadoKeyNotPresentException
.Normalmente lo resolverías sincronizando, pero con un mapa concurrente que, por supuesto, no funcionará. Por lo tanto, la firma de
get
tuvo que cambiar, y la única forma de hacerlo de una manera compatible con versiones anteriores era evitar que el usuario inserte valores nulos en primer lugar, y continuar usándolo como un marcador de posición para "clave no encontrada".fuente
map.getOrDefault(key, NULL_MARKER)
. Si es asínull
, el valor eranull
. Si vuelveNULL_MARKER
, el valor no estaba presente.Josh Bloch diseñado
HashMap
; Doug Lea diseñadoConcurrentHashMap
. Espero que eso no sea calumnioso. En realidad, creo que el problema es que los nulos a menudo requieren envoltura para que el nulo real pueda significar sin inicializar. Si el código del cliente requiere valores nulos, entonces puede pagar el costo (ciertamente pequeño) de envolver los valores nulos.fuente
No se puede sincronizar en un nulo.
Editar: Esto no es exactamente por qué en este caso. Inicialmente pensé que estaba ocurriendo algo interesante al bloquear cosas contra actualizaciones concurrentes o usar el monitor de objetos para detectar si algo se modificó, pero al examinar el código fuente parece que estaba equivocado: se bloquean usando un "segmento" basado en un máscara de bits del hash.
En ese caso, sospecho que lo hicieron para copiar Hashtable, y sospecho que Hashtable lo hizo porque en el mundo de la base de datos relacional, null! = Null, por lo que usar un nulo como clave no tiene sentido.
fuente
ConcurrentHashMap es seguro para subprocesos. Creo que no permitir claves y valores nulos fue parte de garantizar que sea seguro para subprocesos.
fuente
Supongo que el siguiente fragmento de la documentación de la API da una buena pista: "Esta clase es totalmente interoperable con Hashtable en programas que dependen de la seguridad de su hilo pero no de sus detalles de sincronización".
Probablemente solo querían hacer que sea
ConcurrentHashMap
totalmente compatible / intercambiableHashtable
. Y comoHashtable
no permite claves y valores nulos.fuente
No creo que rechazar el valor nulo sea una opción correcta. En muchos casos, queremos poner una clave con valor nulo en el mapa actual. Sin embargo, al usar ConcurrentHashMap, no podemos hacer eso. Sugiero que la próxima versión de JDK pueda soportar eso.
fuente