views:

1125

answers:

4

The JavaDoc of ConcurrentHashMap says this:

Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value.

My question: why?

2nd question: why doesn't Hashtable allow null?

I've used a lot of HashMaps for storing data. But when changing to ConcurrentHashMap I got several times into trouble because of NullPointerExceptions.

+1  A: 

ConcurrentHashMap is thread-safe. I believe that not allowing null keys and values was a part of making sure that it is thread-safe.

Kevin Crowell
+3  A: 

You can't synchronize on a null.

Edit: This isn't exactly why in this case. I initially thought there was something fancy going on with locking things against concurrent updates or otherwise using the Object monitor to detect if something was modified, but upon examining the source code it appears I was wrong - they lock using a "segment" based on a bitmask of the hash.

In that case, I suspect they did it to copy Hashtable, and I suspect Hashtable did it because in the relational database world, null != null, so using a null as a key has no meaning.

Paul Tomblin
Huh? There is no synchronization done on the keys and values of a Map. That would make no sense.
Tobias Müller
There is other sorts of locking done. That's what makes it "Concurrent". In order to do that, it needs an Object to hang on.
Paul Tomblin
Why isn't there a speciall Object internally that could be used for synchronizing null values? e.g. "private Object NULL = new Object();". I think I've seen this before...
Marcel
What other sorts of locking do you mean?
Tobias Müller
I have wondered this myself, @Paul your explanation opened a light from heaven for me. Thanks. +1
WolfmanDragon
Actually, now that I look at the source code http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/ConcurrentHashMap.java I'm having serious doubts about that. It appears it uses segment locking, not locking on individual items.
Paul Tomblin
It does use segment locking, but at the same time it only makes sense that having to read a null that might be a Number as someone tries to read it out as a string as this person uses said number.toString() to create another mapping to be a no no. Like I said, A light from heaven.
WolfmanDragon
Paul, please note that the source you linked is not the current official Sun source, but what looks like a draft for JSR-166. The details are essentially the same however.
Soonil
A: 

I guess that the following snippet of the API documentation gives a good hint: "This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details."

They probably just wanted to make ConcurrentHashMap fully compatible/interchangeable to Hashtable. And as Hashtable does not allow null keys and values..

Tobias Müller
And why doesn't Hashtable support null?
Marcel
From looking at its code, I don't see an obvious reason why Hashtable does not allow null values. Maybe it was just an API decision from back when the class was created?! HashMap has some special handling for the null-case internally which Hashtable does not. (It always throws NullPointerException.)
Tobias Müller
+1  A: 

Josh Bloch designed HashMap; Doug Lea designed ConcurrentHashMap. I hope that isn't libelous. Actually I think the problem is that nulls often require wrapping so that the real null can stand for uninitialised. If client code requires nulls then it can pay the (admittedly small) cost of wrapping nulls itself.

Tom Hawtin - tackline