C

Core Java tutorial for beginners

Clean • Professional

ConcurrentHashMap in Java – Internal Working, Thread Safety & Examples

7 minute

ConcurrentHashMap in Java

ConcurrentHashMap is a high-performance, thread-safe version of HashMap designed for concurrent access by multiple threads. It is part of the java.util.concurrent package and introduced in Java 5 as part of the Java Concurrency API.

Unlike HashMap, it does not throw ConcurrentModificationException when modified during iteration and provides better performance than synchronized HashMap or Hashtable.


What is ConcurrentHashMap?

A ConcurrentHashMap is a thread-safe hash table that supports:

  • Multiple threads reading/writing concurrently without corrupting data.
  • Thread-safe operations without locking the entire map.
  • Atomic operations for putIfAbsent, compute, merge.
  • Fail-safe iterators (weakly consistent).
  • No null keys or null values.

Key Points:

  • Part of the Java Collections Framework (java.util.concurrent).
  • High performance under concurrent access.
  • Ideal for multi-threaded applications like caches, session stores, or shared counters.

Package

import java.util.concurrent.ConcurrentHashMap;

Collection Hierarchy

learn code with durgesh images

Implements:

  • ConcurrentMap<K, V>
  • Serializable
  • Cloneable

Features of ConcurrentHashMap in Java

learn code with durgesh images

1. Thread-Safe

  • Designed for concurrent access by multiple threads.
  • Multiple threads can read and write without corrupting the data.

2. High Performance

  • Uses fine-grained locking (segment/bin-level) in Java 8+, instead of locking the entire map.
  • Reads are mostly non-blocking, allowing high throughput.

3. No Null Keys or Values

  • Unlike HashMap, it does not allow null keys or null values.
  • Using null will throw NullPointerException.

4. Implements Map Interface

  • Fully compatible with Map<K, V> interface methods.
  • Supports all typical map operations.

5. Iterator is Weakly Consistent

  • Iterators do not throw ConcurrentModificationException.
  • Reflects the state of the map at some point during or after iteration, but may not include all updates.

6. Atomic Operations

  • Supports atomic methods like putIfAbsent(), compute(), replace(), and merge().
  • Helps avoid explicit synchronization when performing conditional updates.

7. Segmented Locking / CAS

  • Java 7: used segment-based locks.
  • Java 8+: uses CAS operations + synchronized bins, improving concurrency.

8. Fail-Safe Iteration

  • Safe to iterate while other threads are updating the map.
  • Iterators never fail due to concurrent updates.

9. Supports High Concurrency Level

  • Can be tuned for expected number of concurrent updates.
  • Default concurrency level is 16 (Java 7), optimized internally in Java 8+.

10. Memory Efficient

Only locks small portion of the map during updates, reducing contention and overhead.

11. Lambda-friendly (Java 8+)

Supports forEach(), compute(), merge(), and replaceAll() with lambda expressions.


ConcurrentHashMap vs HashMap vs Hashtable

FeatureHashMapHashtableConcurrentHashMap
Thread-safeNoYes (global lock)Yes (segment/bin-level lock)
Null keysYes (1 null)NoNo
Null valuesYesNoNo
IteratorFail-fastFail-fastWeakly consistent (safe)
PerformanceHigh (single-threaded)Low (multi-threaded)High (multi-threaded)
Lock granularityNoneEntire tableSegment/bin level

Constructors of ConcurrentHashMap

1. Default constructor

Creates an empty ConcurrentHashMap with:

  • Initial Capacity: 16
  • Load Factor: 0.75
  • Concurrency Level: Default (internally decided)
ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>();

2. Constructor with initial capacity

Creates a map with the specified initial capacity, allowing you to pre-size the map to reduce resizing operations.

ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>(initialCapacity);

3. Constructor with initial capacity & load factor

Creates a map using:

  • Your custom initial capacity
  • Your custom load factor (how full the map can get before resizing)
ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>(initialCapacity, loadFactor);

4. Constructor with initial capacity, load factor, and concurrency level

Creates a map with custom:

  • Initial capacity
  • Load factor
  • Concurrency level → expected number of threads updating the map concurrently
ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);

Note:
Concurrency level was important in Java 7 (segment-based design).
In Java 8+, segments are removed & concurrencyLevel is only a hint, not a strict value.


ConcurrentHashMap Common Methods

learn code with durgesh images

1. put(K key, V value)

  • Adds a new key-value pair to the map.
  • If the key already exists, its value is updated.

2. putIfAbsent(K key, V value)

  • Adds the entry only if the key is not already present.
  • This is an atomic operation and prevents overwriting values accidentally.

3. get(Object key)

  • Returns the value associated with the given key.
  • If the key does not exist, returns null.

4. remove(Object key)

Removes the entry for the given key.


5. remove(Object key, Object value)

  • Removes the entry only if the current value matches the given value.
  • Useful when multiple threads are updating the map.

6. replace(K key, V value)

Replaces the value for a key if the key already exists.


7. replace(K key, V oldValue, V newValue)

  • Replaces the value only when the old value matches the provided one.
  • This makes updates fully atomic.

8. containsKey(Object key)

Checks whether a given key exists in the map.


9. containsValue(Object value)

Checks whether a value exists in the map.


10. size()

Returns the number of entries present in the map.


11. mappingCount()

  • Same as size() but returns a long instead of int.
  • Useful when the map becomes very large.

12. isEmpty()

Checks whether the map contains zero entries.


13. clear()

Removes all entries from the map.


14. keySet()

Returns a Set view of all keys in the map.


15. values()

Returns a Collection of all values.


16. entrySet()

Returns a Set of all key-value entries.

Iterators returned by this method are weakly consistent, meaning:

  • They do NOT throw ConcurrentModificationException
  • They reflect updates made during iteration

Java 8 Functional & Atomic Methods (Important)

Java 8 introduced several atomic update methods for concurrent maps.

17. compute(K key, BiFunction remappingFunction)

  • Atomically updates the value for the key.
  • Useful for counters, aggregations, etc.

18. computeIfAbsent(K key, Function mappingFunction)

Computes and inserts a value only when the key is missing.


19. computeIfPresent(K key, BiFunction remappingFunction)

Updates the value only when the key already exists.


20. merge(K key, V value, BiFunction remappingFunction)

  • If the key exists → merges the old and new values using the function.
  • If the key does NOT exist → adds the value.
  • This is atomic and very useful for grouping data.

Java 8 Bulk / Parallel Operations

These methods allow scalable parallel processing on large maps.

21. forEach(BiConsumer action)

Applies an action to each entry in a thread-safe manner.


22. forEach(long parallelismThreshold, BiConsumer action)

Runs forEach in parallel if the map size is above the given threshold.


23. search(long parallelismThreshold, BiFunction searchFunction)

  • Searches for a value in parallel.
  • Stops as soon as a result is found.

24. reduce(long parallelismThreshold, BiFunction reducer)

Reduces all map values into a single result (parallel reduction).


25. reduceEntries(), reduceKeys(), reduceValues()

Special versions of reduce focusing only on:

  • Keys
  • Values
  • Entries

Additional Utility Methods

26. newKeySet()

Creates a thread-safe Set backed internally by ConcurrentHashMap.

27. newKeySet(int initialCapacity)

Same as above but with a custom initial capacity.

28. keys()

Returns an Enumeration of keys (legacy style).

29. elements()

Returns an Enumeration of values (legacy style).


Iteration in ConcurrentHashMap

  • Supports fail-safe / weakly consistent iterators.
  • Multiple threads can iterate and modify simultaneously without ConcurrentModificationException.
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
map.put("B", 2);

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

Time Complexity

OperationAverageNotes
get()O(1)Constant time with hashing
put()O(1)Amortized, uses CAS
remove()O(1)Fast deletion
containsKey()O(1)Constant lookup
iterationO(n)Iterates all elements

Advantages

  • High-performance, thread-safe map.
  • Does not block readers while writing.
  • Supports fail-safe iterators.
  • Atomic operations using putIfAbsent, compute, merge.
  • Great for multi-threaded applications.

Disadvantages

  • Slightly higher memory overhead than HashMap.
  • Does not allow null keys or values.
  • More complex internal structure than a simple HashMap.

Real-World Use Cases

  • Multi-threaded caches.
  • Shared counters or lookup tables.
  • Session storage in web applications.
  • Thread-safe data sharing in concurrent apps.

Example – Basic Usage

import java.util.concurrent.ConcurrentHashMap;

public class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        map.put("Java", 1);
        map.put("Python", 2);
        map.putIfAbsent("C++", 3);

        System.out.println(map.get("Python")); // 2

        map.replace("Java", 1, 10);
        map.remove("C++");

        for (var entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

Output:

2
Java = 10
Python = 2

Concurrency in Action

ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
Runnable writer = () -> {
    for(int i = 0; i < 100; i++) {
        map.put(i, Thread.currentThread().getName() + "-" + i);
    }
};

Thread t1 = new Thread(writer, "Thread-1");
Thread t2 = new Thread(writer, "Thread-2");
t1.start(); t2.start();
  • Multiple threads can safely write to the map simultaneously.
  • No ConcurrentModificationException occurs.

Best Practices

  • Prefer ConcurrentHashMap over Hashtable or Collections.synchronizedMap() in multi-threaded apps.
  • Use atomic methods (putIfAbsent, compute, merge) for thread-safe updates.
  • Avoid storing null keys or values.
  • Use Java 8+ lambda methods for clean and efficient iteration.

Article 0 of 0