Here are the key points about ConcurrentHashMap
and HashMap
in Java:
Concurrency:
- ConcurrentHashMap: Designed for concurrent use by multiple threads. It provides thread safety without synchronizing the whole map.
- HashMap: Not thread-safe; if used in a multi-threaded environment without proper synchronization, it can lead to data corruption.
Performance:
- ConcurrentHashMap: Generally provides better performance in multi-threaded scenarios because it uses a segment-level locking mechanism.
- HashMap: Offers better raw performance in single-threaded scenarios since there’s no overhead of locking mechanisms.
Null Keys and Values:
- ConcurrentHashMap: This does not allow null keys or values.
- HashMap: Allows one null key and multiple null values.
Iterators:
- ConcurrentHashMap: Uses a weakly consistent iterator, which means it might not reflect all changes made to the map after the iterator is created but won’t throw a
ConcurrentModificationException
. - HashMap: Provides a fail-fast iterator, meaning if the map is structurally modified after the iterator’s creation, in any way except through the iterator’s own
remove
method, it will throw aConcurrentModificationException
.
Internal Structure:
- ConcurrentHashMap: Divides the map into segments and only locks a particular segment during write operations, which allows concurrent read operations and writes to different segments.
- HashMap: Uses a single array and linked lists (or trees for densely populated buckets in newer versions of Java).
Scalability:
- ConcurrentHashMap: Scales better in a multi-threaded environment due to segment-level locking.
- HashMap: If not synchronized externally, it’s not suitable for multi-threaded environments.
Concurrent Operations:
- ConcurrentHashMap: Provides several atomic operations (like
putIfAbsent
,remove
, andreplace
) which are not available in the standardHashMap
API.
Default Initial Capacity and Load Factor:
- While both have customization options, by default,
HashMap
andConcurrentHashMap
typically use an initial capacity of 16 and a load factor of 0.75.
Difference Between ConcurrentHashMap and HashMap in Java
Criteria | ConcurrentHashMap | HashMap |
---|---|---|
Synchronization | Segment-level locking; allows concurrent read without locking and partially locked writes | Not synchronized |
Performance | Generally better performance in multi-threaded scenarios due to finer-grained locking | Faster in single-threaded scenarios since no locking is involved |
Null Keys and Values | Does not allow null keys or values | Allows one null key and multiple null values |
Fail-Fast | Iterator is weakly consistent and does not throw `ConcurrentModificationException` | Iterator is fail-fast and can throw `ConcurrentModificationException` |
Use-case | When multiple threads need to modify a map concurrently | When thread-safety is not required or is managed externally |
Thread Safety | Yes | No |
Concurrency Level | Allows specifying the concurrency level to divide the map into segments, increasing throughput | Not applicable as it’s unsynchronized |
Example: Difference Between ConcurrentHashMap and HashMap in Java
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapVsHashMapDemo {
public static void main(String[] args) {
// Create a HashMap and add elements
Map<String, String> hashMap = new HashMap<>();
hashMap.put("India", "Delhi");
hashMap.put("Japan", "Tokyo");
hashMap.put("USA", "Washington D.C.");
System.out.println("HashMap:");
hashMap.forEach((key, value) -> System.out.println(key + " -> " + value));
// Create a ConcurrentHashMap and add elements
Map<String, String> concurrentHashMap = new ConcurrentHashMap<>();
concurrentHashMap.put("India", "Delhi");
concurrentHashMap.put("Japan", "Tokyo");
concurrentHashMap.put("USA", "Washington D.C.");
System.out.println("\nConcurrentHashMap:");
concurrentHashMap.forEach((key, value) -> System.out.println(key + " -> " + value));
}
}
Output:
HashMap: India -> Delhi Japan -> Tokyo USA -> Washington D.C. ConcurrentHashMap: India -> Delhi Japan -> Tokyo USA -> Washington D.C.
Explanation:
1. HashMap: A HashMap is an unsynchronized, key-value based map which allows null keys and values. It doesn't guarantee any specific order of entries. It's not thread-safe. When accessed or modified by multiple threads simultaneously, it can produce inconsistent results or even throw ConcurrentModificationException.
2. ConcurrentHashMap: A ConcurrentHashMap is a thread-safe variant of HashMap. It's designed to handle higher levels of concurrency. Instead of locking the entire collection, it divides the map into segments and locks only the necessary segments. This ensures better performance in multi-threaded scenarios. It does not allow null keys or values.
3. In the provided example, both the HashMap and ConcurrentHashMap have the same entries added, and when printed, they display the entries in the order they were added.
4. If you need a map for single-threaded applications or scenarios where map modifications are rare, HashMap is a good choice. However, if you're dealing with concurrent modifications in multi-threaded applications, ConcurrentHashMap should be preferred.