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

Implements:
ConcurrentMap<K, V>SerializableCloneable
Features of ConcurrentHashMap in Java

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(), andmerge(). - 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
| Feature | HashMap | Hashtable | ConcurrentHashMap |
|---|---|---|---|
| Thread-safe | No | Yes (global lock) | Yes (segment/bin-level lock) |
| Null keys | Yes (1 null) | No | No |
| Null values | Yes | No | No |
| Iterator | Fail-fast | Fail-fast | Weakly consistent (safe) |
| Performance | High (single-threaded) | Low (multi-threaded) | High (multi-threaded) |
| Lock granularity | None | Entire table | Segment/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

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
| Operation | Average | Notes |
|---|---|---|
get() | O(1) | Constant time with hashing |
put() | O(1) | Amortized, uses CAS |
remove() | O(1) | Fast deletion |
containsKey() | O(1) | Constant lookup |
| iteration | O(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
ConcurrentModificationExceptionoccurs.
Best Practices
- Prefer
ConcurrentHashMapoverHashtableorCollections.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.
