Difference between Hashtable and Collections.synchronizedMap(HashMap)
As far as I know, java.util.Hashtable
synchronizes each and every method in the java.util.Map
interface, while Collections.synchronizedMap(hash_map)
returns a wrapper object containing synchronized methods delegating calls to the actual hash_map
(correct me if I am wrong).
I have two questions :
What difference does it make to synchronize each and every method and to have a wrapper class? What are the scenarios to choose one over the other?
What happens when we do
Collections.synchronizedMap(hash_table)
? Will this be equal to simply using a normaljava.util.Hashtable
?
Solution 1:
One more difference that I can find at the implementation of both the classes is as follows:
• The Hashtable
class has all its methods synchronized i.e. the locking is done at the method level and hence one can say that the mutex is always at the Hashtable
object (this
) level.
• The method Collections.synchronizedMap(Map)
returns an instance of SynchronizedMap
which is an inner class to the Collections
class. This class has all its methods in a Synchronized
block with a mutex. The difference lies in the mutex here. The inner class SynchronizedMap
has two constructors, one which takes only Map
as an argument and another which takes a Map
and an Object
(mutex) as an argument. By default if one uses the first constructor of passing only a Map
, this
is used as a mutex. Though, the developer is allowed to pass another object of mutex as a second argument by which the lock on the Map
methods would be only on that Object
and hence less restrictive than Hashtable
.
• Hence, Hashtable
uses method level synchronization but Collections.synchronizedMap(Map)
provides a flexibility to developer lock on provided mutex with Synchronized
block.
Solution 2:
Here are the answers I've gotten from a bit of (hopefully correct) research:
Both provide the same degree of synchronization. If you were to wrap
Hashtable
through Collections.synchronized you would have the same degree, but with another redundant layer, of synchronization.The main difference between
Hashtable
andCollections.synchronizedMap(HashMap)
exist more at the API level. BecauseHashtable
is part of Java's legacy code, you'll see that theHashtable
API is enhanced to implement theMap
interface, to become part of Java's collections framework. This means that if you were to wrapHashtable
throughCollections.synchronizedMap()
, the API of the wrappedHashtable
would become limited to theMap
API. So if the API ofHashtable
is encompassed in your definition of behavior, then it is obviously altered/limited.
Solution 3:
The first associative collection class to appear in the Java class library was Hashtable, which was part of JDK 1.0. Hashtable provided an easy-to-use, thread-safe, associative map capability, and it was certainly convenient. However, the thread-safety came at a price -- all methods of Hashtable were synchronized. At that time, uncontended synchronization had a measurable performance cost. The successor to Hashtable, HashMap, which appeared as part of the Collections framework in JDK 1.2, addressed thread-safety by providing an unsynchronized base class and a synchronized wrapper, Collections.synchronizedMap. Separating the base functionality from the thread-safety Collections.synchronizedMap allowed users who needed synchronization to have it, but users who didn't need it didn't have to pay for it.
The simple approach to synchronization taken by both Hashtable and synchronizedMap -- synchronizing each method on the Hashtable or the synchronized Map wrapper object -- has two principal deficiencies. It is an impediment to scalability, because only one thread can access the hash table at a time. At the same time, it is insufficient to provide true thread safety, in that many common compound operations still require additional synchronization. While simple operations such as get() and put() can complete safely without additional synchronization, there are several common sequences of operations, such as iteration or put-if-absent, which still require external synchronization to avoid data races.
The following link is the source and has more information: Concurrent Collections Classes
Solution 4:
The difference is not all at the obvious API level and there are many subtleties at the implementation level. For example, Hashtable
doesn't sport HashMap
's advanced recalculation of supplied keys' hashcodes that reduces hash collisions. On the other hand, Hashtable#hashCode()
avoids infinite recursion for self-referential hashtables to allow "certain 1.1-era applets with self-referential hash tables to work".
In general, though, one shouldn't count on Hashtable
receiving any further improvements or refinements beyond basic correctness and backward compatibility. It is considered a relic from the deep Java past.
Solution 5:
Another point of difference to note is that HashTable does not allow null keys or values whereas HashMap allows one null key and any number of null values. Since synchronizedMap is wrapper over HashMap, its behavior with respect to null keys and values is same as HashMap.