O JavaDoc de ConcurrentHashMap
diz o seguinte:
De maneira semelhante,
Hashtable
mas diferenteHashMap
, essa classe não permitenull
ser usada como chave ou valor.
Minha pergunta: por que?
2ª pergunta: Por que não Hashtable
permite nulo?
Eu usei muitos HashMaps para armazenar dados. Mas, ao mudar para ConcurrentHashMap
, fiquei várias vezes com problemas por causa de NullPointerExceptions.
java
concurrenthashmap
Marcel
fonte
fonte
Respostas:
Do autor de
ConcurrentHashMap
si mesmo (Doug Lea) :fonte
Optional
s como valores internamenteOptional
é um recurso do Java 8, que não estava disponível na época (Java 5). Você poderia usarOptional
s agora, de fato.Acredito que é, pelo menos em parte, permitir que você combine
containsKey
e façaget
uma única ligação. Se o mapa puder conter nulos, não há como saber seget
está retornando um nulo porque não havia chave para esse valor ou apenas porque o valor era nulo.Por que isso é um problema? Porque não há maneira segura de fazer isso sozinho. Pegue o seguinte código:
Como
m
é um mapa simultâneo, a chave k pode ser excluída entre as chamadascontainsKey
eget
, fazendo com que esse trecho retorne um nulo que nunca estava na tabela, e não o desejadoKeyNotPresentException
.Normalmente você resolveria isso sincronizando, mas com um mapa simultâneo que, obviamente, não funcionaria. Daí a assinatura para
get
teve que mudar, e a única maneira de fazer isso de maneira compatível com versões anteriores era impedir o usuário inserir valores nulos em primeiro lugar e continuar usando-o como um espaço reservado para "chave não encontrada".fonte
map.getOrDefault(key, NULL_MARKER)
. Se fornull
, o valor foinull
. Se retornarNULL_MARKER
, o valor não estava presente.Josh Bloch projetou
HashMap
; Doug Lea projetouConcurrentHashMap
. Espero que não seja difamatório. Na verdade, acho que o problema é que os nulos geralmente exigem quebra automática para que o nulo real possa significar não inicializado. Se o código do cliente exigir nulos, ele poderá pagar o custo (reconhecidamente pequeno) de agrupar os nulos.fonte
Você não pode sincronizar em um nulo.
Edit: Não é exatamente por isso que neste caso. Inicialmente, pensei que havia algo extravagante em bloquear as atualizações simultâneas ou usar o monitor de objetos para detectar se algo foi modificado, mas, ao examinar o código - fonte , parece que eu estava errado - eles bloqueiam usando um "segmento" baseado em um máscara de bit do hash.
Nesse caso, suspeito que eles fizeram isso para copiar o Hashtable, e suspeito que o Hashtable fez isso porque no mundo do banco de dados relacional, null! = Null, portanto, usar um null como chave não tem significado.
fonte
ConcurrentHashMap é seguro para threads. Acredito que não permitir chaves e valores nulos fazia parte de garantir que seja seguro para threads.
fonte
Acho que o seguinte trecho da documentação da API fornece uma boa dica: "Essa classe é totalmente interoperável com o Hashtable em programas que dependem da segurança do encadeamento, mas não dos detalhes da sincronização".
Eles provavelmente só queriam tornar
ConcurrentHashMap
totalmente compatíveis / intercambiáveis paraHashtable
. E comoHashtable
não permite chaves e valores nulos.fonte
Eu não acho que não permitir valor nulo é uma opção correta. Em muitos casos, queremos colocar uma chave com valor nulo no mapa atual. No entanto, usando ConcurrentHashMap, não podemos fazer isso. Sugiro que a próxima versão do JDK possa suportar isso.
fonte