Le JavaDoc de ConcurrentHashMap
dit ceci:
Comme
Hashtable
mais contrairementHashMap
, cette classe ne permet pasnull
d'être utilisée comme clé ou valeur.
Ma question: pourquoi?
2ème question: pourquoi n'autorise pas la valeur Hashtable
NULL?
J'ai utilisé beaucoup de HashMaps pour stocker des données. Mais lors du passage à, ConcurrentHashMap
j'ai eu plusieurs fois des ennuis à cause de NullPointerExceptions.
java
concurrenthashmap
Marcel
la source
la source
Réponses:
De l'auteur de
ConcurrentHashMap
lui - même (Doug Lea) :la source
Optional
s comme valeurs en interneOptional
est une fonctionnalité Java 8, qui n'était pas disponible à l'époque (Java 5). Vous pouvez utiliserOptional
s maintenant, en effet.Je crois que c'est, au moins en partie, pour vous permettre de combiner
containsKey
etget
en un seul appel. Si la carte peut contenir des valeurs nulles, il n'y a aucun moyen de dire siget
renvoie une valeur nulle car il n'y avait pas de clé pour cette valeur, ou simplement parce que la valeur était nulle.Pourquoi c'est un problème? Parce qu'il n'y a pas de moyen sûr de le faire vous-même. Prenez le code suivant:
Puisqu'il
m
s'agit d'une mappe simultanée, la clé k peut être supprimée entre les appelscontainsKey
etget
, ce qui fait que cet extrait de code renvoie une valeur null qui n'a jamais été dans la table, plutôt que celle souhaitéeKeyNotPresentException
.Normalement, vous résoudriez cela en synchronisant, mais avec une carte simultanée, cela ne fonctionnera bien sûr pas. Par conséquent, la signature pour
get
devait changer, et la seule façon de le faire d'une manière rétrocompatible était d'empêcher l'utilisateur d'insérer des valeurs nulles en premier lieu, et de continuer à l'utiliser comme espace réservé pour "clé non trouvée".la source
map.getOrDefault(key, NULL_MARKER)
. Si c'est le casnull
, la valeur étaitnull
. S'il renvoieNULL_MARKER
, la valeur n'était pas présente.Josh Bloch a conçu
HashMap
; Doug Lea a conçuConcurrentHashMap
. J'espère que ce n'est pas diffamatoire. En fait, je pense que le problème est que les nulls nécessitent souvent un wrapping afin que le vrai null puisse représenter non initialisé. Si le code client nécessite des valeurs nulles, il peut payer le coût (certes faible) de l'encapsulation des valeurs nulles lui-même.la source
Vous ne pouvez pas synchroniser sur une valeur nulle.
Edit: Ce n'est pas exactement pourquoi dans ce cas. J'ai d'abord pensé qu'il se passait quelque chose d'extraordinaire avec le verrouillage des choses contre les mises à jour simultanées ou l'utilisation du moniteur d'objets pour détecter si quelque chose avait été modifié, mais en examinant le code source il semble que j'avais tort - ils se verrouillent à l'aide d'un «segment» basé sur masque binaire du hachage.
Dans ce cas, je soupçonne qu'ils l'ont fait pour copier Hashtable, et je suppose que Hashtable l'a fait parce que dans le monde des bases de données relationnelles, null! = Null, donc utiliser un null comme clé n'a aucune signification.
la source
ConcurrentHashMap est thread-safe. Je crois que ne pas autoriser les clés et les valeurs nulles faisait partie de la garantie de la sécurité des threads.
la source
Je suppose que l'extrait suivant de la documentation de l'API donne un bon indice: "Cette classe est entièrement interopérable avec Hashtable dans les programmes qui reposent sur sa sécurité de thread mais pas sur ses détails de synchronisation."
Ils voulaient probablement juste rendre
ConcurrentHashMap
entièrement compatible / interchangeableHashtable
. Et commeHashtable
n'autorise pas les clés et valeurs nulles.la source
Je ne pense pas que l'interdiction de la valeur nulle soit une option correcte. Dans de nombreux cas, nous voulons mettre une clé avec une valeur nulle dans la carte concourante. Cependant, en utilisant ConcurrentHashMap, nous ne pouvons pas faire cela. Je suggère que la prochaine version de JDK puisse prendre en charge cela.
la source