A ConcurrentHashMap
is a thread-safe collection used to store key-value pairs, similar to a regular HashMap
, but with the added advantage of supporting concurrent access by multiple threads. This makes it ideal for situations where multiple threads need to read and write to the map simultaneously, without compromising performance or thread safety.
In a regular HashMap
, if two threads try to update the same entry simultaneously, it can lead to unpredictable behavior, such as data corruption. However, ConcurrentHashMap
is specifically designed to handle these types of scenarios efficiently, without requiring the entire map to be locked.
Features
- Thread-Safety:
ConcurrentHashMap
allows multiple threads to read from the map at the same time, and threads can also modify different parts of the map simultaneously without blocking each other. - No Global Locking: Unlike some other thread-safe collections,
ConcurrentHashMap
does not lock the entire map when a thread is writing to it. Instead, it locks only the specific segment of the map being accessed. This leads to better performance compared to other synchronized collections. - Efficient Reads: Since the map is partitioned into segments, many threads can read data concurrently without waiting for each other. This improves the map’s overall performance when used in multi-threaded applications.
- Atomic Operations: Operations like
putIfAbsent()
,replace()
, andremove()
are atomic, which means they can be safely executed in a multi-threaded environment.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapOperations { public static void main(String[] args) { // Create a ConcurrentHashMap ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); // 1. Adding elements map.put("Java", "Great"); map.put("Python", "Awesome"); map.put("JavaScript", "Versatile"); // Display the map after adding elements System.out.println("After adding elements: " + map); // 2. Checking if a key exists boolean hasJava = map.containsKey("Java"); System.out.println("Contains 'Java' key? " + hasJava); // 3. Checking if a value exists boolean hasGreat = map.containsValue("Great"); System.out.println("Contains value 'Great'? " + hasGreat); // 4. Getting a value by key String javaValue = map.get("Java"); System.out.println("Value for 'Java': " + javaValue); // 5. Replacing a value map.replace("Python", "Incredible"); System.out.println("After replacing 'Python' value: " + map); // 6. Conditional replace (only if the key exists with a specific value) boolean replaced = map.replace("Java", "Great", "Fantastic"); System.out.println("Was 'Java' replaced? " + replaced); System.out.println("After conditional replace: " + map); // 7. Remove an entry by key String removedValue = map.remove("JavaScript"); System.out.println("Removed 'JavaScript': " + removedValue); System.out.println("After removal: " + map); // 8. Put only if the key is absent map.putIfAbsent("Java", "Amazing"); System.out.println("After putIfAbsent for 'Java': " + map); // 9. Iterating over keys and values System.out.println("Iterating over map:"); map.forEach((key, value) -> { System.out.println(key + ": " + value); }); // 10. Merge two values for a key (if key exists, merge the values) map.merge("Python", "Great", (oldValue, newValue) -> oldValue + " and " + newValue); System.out.println("After merge for 'Python': " + map); // 11. Clearing the map map.clear(); System.out.println("After clearing: " + map); } } |
Use Cases
- Web Applications: Storing session data or caches accessed by multiple threads.
- Microservices: Shared in-memory data structures for service-level caches.
- Real-time Systems: Applications like gaming servers or financial systems needing fast, thread-safe data access.
- Multithreaded Programs: Any multi-threaded program requiring a shared, mutable map.