53

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 :

  1. 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?

  2. What happens when we do Collections.synchronizedMap(hash_table)? Will this be equal to simply using a normal java.util.Hashtable?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Vinoth Kumar C M
  • 10,378
  • 28
  • 89
  • 130
  • possible duplicate of [Differences between HashMap and Hashtable?](http://stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable) – MK. Jan 16 '12 at 04:20
  • 23
    This is not a duplicate of *that* question. This is comparing the synchronized wrapper over a HashMap (or HashTable) with a HashTable. –  Jan 16 '12 at 04:38
  • 1
    I'd be interested to know if there are differences in performance, which none of the current answers address. Calling methods of a `Collections.synchronizedMap` via a variable of type Map means there are 2 interface virtual calls before you get to the implementation, whereas with Hashtable, there is at most 1 virtual call, and you could declare your variable as type Hashtable directly, and do it with 0 virtual calls. But perhaps HashMap differs in other ways that make it faster overall. – Boann Aug 17 '13 at 18:50

6 Answers6

75

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.

Alexey
  • 2,542
  • 4
  • 31
  • 53
mankadnandan
  • 1,033
  • 1
  • 8
  • 11
  • 6
    What a beautiful answer, underlining what remain untouched otherwise in rest answers. +1 – Raúl Mar 27 '15 at 15:12
  • 3
    Extra constructor and synchronization at block level (unlike method level for HashTable) are the keys. – Raúl Mar 27 '15 at 15:14
  • 8
    This is really interesting information, but the inner SynchronizedMap class is private, and there is no static method corresponding to the version of the constructor that accepts a mutex object as an argument, so the developer cannot really provide a custom mutex, right? – CarLuva Oct 29 '15 at 18:36
  • @CarLuva You are right. I don't see any method exposed to use the second contructor. – mankadnandan Nov 26 '15 at 05:05
  • Do i understand correctly that `Hashtable` and `Collections.synchronizedMap` are both blocking collections and are almost the same under the hood? – pacman Aug 28 '16 at 01:02
  • but how 2nd contructor will be called, we are only doing Collections.synchronizedMap(Map) – Diana May 15 '18 at 13:26
  • https://stackoverflow.com/questions/50829463/purpose-of-overloaded-constructor-in-synchronizedmap-class/50829585#50829585 – Somnath Musib Jun 13 '18 at 05:36
17

Here are the answers I've gotten from a bit of (hopefully correct) research:

  1. 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.

  2. The main difference between Hashtable and Collections.synchronizedMap(HashMap) exist more at the API level. Because Hashtable is part of Java's legacy code, you'll see that the Hashtable API is enhanced to implement the Map interface, to become part of Java's collections framework. This means that if you were to wrap Hashtable through Collections.synchronizedMap(), the API of the wrapped Hashtable would become limited to the Map API. So if the API of Hashtable is encompassed in your definition of behavior, then it is obviously altered/limited.

roottraveller
  • 7,942
  • 7
  • 60
  • 65
Nadir Muzaffar
  • 4,772
  • 2
  • 32
  • 48
  • adding to it, Hashtable methods are synchronized whereas Synchronized map's method implementations have synchronized maps on a mutex. – Gaurav Aug 18 '20 at 12:32
4

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.

Rahul Jangra
  • 949
  • 6
  • 5
  • 2
    Irrelevant answer – Mr.Q Feb 16 '19 at 08:16
  • 2
    This directly answers the question posed in the title, which certainly makes it relevant. This is true even if the question body poses a more specific set of questions. Remember that people often find and read questions based on the title, and this answer is productive for those people. Losing this answer would reduce the usefulness of this question in aggregate. – AndrewF Feb 18 '22 at 02:27
4

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

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
bchetty
  • 2,231
  • 1
  • 19
  • 26
  • 1
    The second paragraph says that `Hashtable` and `synchronizedMap` is the same thing. Which means we haven't answered the question at all: What's their difference? – Pacerier Aug 20 '14 at 14:54
3

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.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
2

At the risk of stating the obvious (or being plain wrong) isn't the difference that

The synchronization wrappers add automatic synchronization (thread-safety) to an arbitrary collection

http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html and continues to say

A collection created in this fashion is every bit as thread-safe as a normally synchronized collection, such as a Vector.

You may like to see this thread for issues regarding HashMaps and concurrency - Hashmap concurrency issue (or you are possibly very much aware of them already). A good example is:

The conditions you describe will not be satisfied by HashMap. Since the process of updating a map is not atomic you may encounter the map in an invalid state. Multiple writes might leave it in a corrupted state. ConcurrentHashMap (1.5 or later) does what you want.

https://stackoverflow.com/a/1003071/201648

I guess in terms of "when should I use this" I would tend to use the syncronised collection where concurrency is required, otherwise you may be creating more work for yourself (see below).

In terms of altering the behavior

If an explicit iterator is used, the iterator method must be called from within the synchronized block. Failure to follow this advice may result in nondeterministic behavior

There are more consequences of using synchronization given at the (Oracle) link provided.

Community
  • 1
  • 1
Aaron Newton
  • 2,124
  • 1
  • 28
  • 31