March 13, 2024

HashMap Vs ConcurrentHashMap in Java

ConcurrentHashMap in Java is a thread safe Map implementation which provides another alternative to be used in a multithreaded environment apart from HashTable or explicitly synchronizing HashMap. Where as HashMap in Java is not synchronized so not thread safe but provides better performance. In this post we’ll see the differences between HashMap and ConcurrentHashMap in Java.

HashMap Vs ConcurrentHashMap in Java

1- Thread safety:

One of the main difference between HashMap and ConcurrentHashMap is that ConcurrentHashMap is thread safe and can be used in concurrent environment.

HashMap is not thread safe and sharing HashMap’s instance in a multi-threaded environment will give unpredictable results.

2- How synchronization is done:

HashMap can be synchronized externally by using Collections.synchronizedMap() method which returns a synchronized Map backed by the specified map. Note that synchronizing a HashMap this way synchronizes all the methods of the HashMap on a single lock. Read more about HashMap synchronization in this post- How to Synchronize HashMap in Java

ConcurrentHashMap is already thread safe so no external synchronization needed. ConcurrentHashMap provides better concurrency by locking only a portion of the Map. Map is divided into partitions based on the passed concurrency level. By default concurrency level is 16. That means 16 threads can modify ConcurrentHashMap if all those threads are accessing different partitions of the Map.
ConcurrentHashMap allows retrieval operations (for example get) to overlap with update operations (for example put and remove) as retrieval operations generally do not block. This helps in improving the performance of the ConcurrentHashMap.

3- Iterator fail-fast or fail-safe

The iterators returned by HashMap's "collection view methods" are fail-fast. If the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.

Iterator returned by ConcurrentHashMap's "collection view methods" are fail-safe and does not throw ConcurrentModificationException if the map is structurally modified at any time after the iterator is created.

Here is an example showing the iteration using an iterator with both HashMap and ConcurrentHashMap.

public class HashMapDemo {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> carMap = new HashMap<String, String>();
    // Storing elements
    carMap.put("1", "Audi");
    carMap.put("2", "BMW");
    carMap.put("3", "Jaguar");
    carMap.put("4", "Mini Cooper");

    Set<String> carSet =  carMap.keySet();
    Iterator<String> itr = carSet.iterator();
    while (itr.hasNext()) {
      String key = itr.next();
      System.out.println("Key is " + key + " Value is " + carMap.get(key));    
      // removing value using HashMap's remove method
      if(key.equals("2")){
        carMap.remove(key);
      }
    }
  }
}
Output
Key is 1 Value is Audi
Key is 2 Value is BMW
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextNode(Unknown Source)
	at java.util.HashMap$KeyIterator.next(Unknown Source)
	at com.knpcode.HashMapDemo.main(HashMapDemo.java:22)

As you can see ConcurrentModificationException exception is thrown as you are trying to structurally modify the HashMap while it is iterated using an iterator.

Where as in case of ConcurrentHashMap-

public class FailSafeDemo {
  public static void main(String[] args) {
    Map<String, String> carMap = new ConcurrentHashMap<String, String>();
    carMap.put("1", "Audi");
    carMap.put("2", "BMW");
    carMap.put("3", "Jaguar");
    carMap.put("4", "Mini Cooper");
    // iterating map
    Iterator<Map.Entry<String, String>> itr = carMap.entrySet().iterator();
    while(itr.hasNext()) {
      Map.Entry<String, String> entry = itr.next();
      System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
      carMap.put("5", "Mercedes");
    }
    System.out.println("Size- " + carMap.size());
  }
}
Output
Key is 1 Value is Audi
Key is 2 Value is BMW
Key is 3 Value is Jaguar
Key is 4 Value is Mini Cooper
Key is 5 Value is Mercedes
Size- 5

As you can see while iterating the ConcurrentHashMap a new element is added to it, that does not result in ConcurrentModificationException being thrown.

4- Allowing null

HashMap permits null values and the null key.

ConcurrentHashMap does not allow null to be used as a key or value.

5- Performance

HashMap is faster as it is not synchronized. If HashMap instance has to be shared among multiple threads and it has to be synchronized externally then HashMap is slower in comparison to ConcurrentHashMap as the whole HashMap is synchronized on a single lock in such scenario where as ConcurrentHashMap uses separate locks for separate buckets thus providing much better concurrency level.

That's all for the topic HashMap Vs ConcurrentHashMap in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment