This post will discuss the major difference between ConcurrentHashMap and HashTable classes, and Collections.synchronizedMap() method in Java.

1. Overview of ConcurrentHashMap class

The ConcurrentHashMap class, as the name suggests, is designed to support concurrency and high performance in multithreaded applications. It allows multiple threads to read and write to the map concurrently without blocking or locking them. It implements the ConcurrentMap interface, which extends the Map interface, and uses a hash table as the underlying data structure to store key-value pairs.

It works by dividing the map into several segments or buckets based on the hash code of the keys, where each segment has its own lock that controls the access and modification of the key-value pairs in that segment. By default, ConcurrentHashMap has 16 segments, which means that it can support up to 16 concurrent write operations at a time. However, this number can be changed by specifying the concurrency level parameter in the constructor of ConcurrentHashMap.

ConcurrentHashMap also provides some atomic operations that can be performed on the map without locking or synchronization, such as putIfAbsent(), replace(), remove(), and compute(). These operations are useful for implementing common patterns such as check-and-act, compare-and-swap, and compute-if-absent. Here is an example of how to create and use a ConcurrentHashMap in Java:

Download  Run Code

2. Overview of HashTable class

Hashtable is a legacy class that implements the Map interface and uses a hash table as the underlying data structure to store key-value pairs. It is similar to HashMap in many aspects, but it is synchronized by default. Every method in HashTable is synchronized, which means that only one thread can access or modify the table at a time. This ensures that HashTable is consistent and coherent across all threads, but also reduces its concurrency and performance. Here is an example of how to create and use a HashTable in Java:

Download  Run Code

3. Overview of Collections.synchronizedMap() method

The Collections.synchronizedMap() method creates a thread-safe or synchronized map from an existing map, such as HashMap or TreeMap or LinkedHashMap. It takes a map object as a parameter and returns a synchronized (thread-safe) map backed by the specified map. It uses a single lock to control the access and modification of the entire map. This means that only one thread can read or write to the map at a time, while other threads have to wait until the lock is released. This ensures that the map is consistent and coherent across all threads, but also reduces the concurrency and performance of the map.

Here is an example of how to create and use a Collections.synchronizedMap() in Java:

Download  Run Code

4. Difference between ConcurrentHashMap, HashTable, and Collections.synchronizedMap()

Here are some differences between ConcurrentHashMap class, Collections.synchronizedMap() method, and HashTable class in Java:

1. Concurrency

  • ConcurrentHashMap is a concurrent version of the standard HashMap class, which allows the concurrent modification of a map by multiple threads. It works by locking the bucket which is being updated while other buckets are free to be accessed by other threads.
  • Unlike ConcurrentHashMap, Collections.SynchronizedMap locks the entire table, blocking parallel access for multiple threads. In other words, only one thread can access the map, which ultimately leads to poor performance.
  • Like ConcurrentHashMap, Hashtable implementation is also synchronized, but it acquires the lock on the entire map instance.

2. Null values

ConcurrentHashMap and Hashtable does not permit null keys or values. If we try to insert a null key or value, we will get a NullPointerException.

  • The behavior of Collections.SynchronizedMap() depends on the backing map. If null keys and values are required, HashMap can be used as the backing set.

3. Fail-safe or Fail-fast behavior

  • The iterator returned by the ConcurrentHashMap is weakly consistent, which never throws ConcurrentModificationException even if the map is modified after the construction of the iterator. It makes no guarantees to reflect any modifications after its construction.
  • Collections.SynchronizedMap() does not guarantee a fail-safe iterator on concurrent modification (one thread is updating the map, and another thread is traversing the map using an iterator). The fail-safe or fail-fast behavior totally depends on the backing map.
  • The iterator returned by the Hashtable class is fail-fast and throws a ConcurrentModificationException if the map is structurally modified after creating the iterator. Hashtable is also traversed by Enumerator, which is fail-safe. The results are undefined if the Hashtable is structurally modified after the enumeration is created.

4. Iteration Order

  • ConcurrentHashMap and HashTable do not preserve the insertion order of mappings in the map. Also, the addition and removal of any element might change its iteration order.
  • Collections.SynchronizedMap() is backed by the specified map and retains the insertion order of the map. If HashMap is passed to it, the order of the map is undefined, and if a TreeMap is used, the order is the same as the natural ordering of its keys or that of a provided Comparator.

5. What to use and when?

Here are some general recommendations on choosing between ConcurrentHashMap, HashTable, and Collections.synchronizedMap():

  • If you need a map that can handle multiple concurrent write and update operations without blocking or locking threads, we should use ConcurrentHashMap. It can be used on performance-critical systems, where there are far more update operations on the map than the read operations.
  • If you need a map that can ensure thread safety and synchronization across all threads, we should use Collections.synchronizedMap(). It can be used when data consistency is important.
  • If you need map that can work with older versions of Java or legacy codebases, we should use HashTable. However, Javadoc recommends using ConcurrentHashMap in place of Hashtable for thread-safe highly concurrent implementation.

That’s all about the ConcurrentHashMap, HashTable, and Collections.synchronizedMap() in Java.