Java ConcurrentHashMap class is part of the Concurrency Collection Classes. It’s a hash table implementation, which supports concurrent retrieval and updates. It’s used in a multi-threaded environment to avoid ConcurrentModificationException.
If we try to modify the collection while iterating over it, we get ConcurrentModificationException
. Java 1.5 introduced Concurrent classes in the java.util.concurrent
package to overcome this scenario. ConcurrentHashMap is the Map implementation that allows us to modify the Map while iteration. The ConcurrentHashMap operations are thread-safe. ConcurrentHashMap doesn’t allow null for keys and values.
The ConcurrentHashMap
class is similar to HashMap, except that it’s thread-safe and allows modification while iteration.
package com.journaldev.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
//ConcurrentHashMap
Map<String,String> myMap = new ConcurrentHashMap<String,String>();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
myMap.put("4", "1");
myMap.put("5", "1");
myMap.put("6", "1");
System.out.println("ConcurrentHashMap before iterator: "+myMap);
Iterator<String> it = myMap.keySet().iterator();
while(it.hasNext()){
String key = it.next();
if(key.equals("3")) myMap.put(key+"new", "new3");
}
System.out.println("ConcurrentHashMap after iterator: "+myMap);
//HashMap
myMap = new HashMap<String,String>();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
myMap.put("4", "1");
myMap.put("5", "1");
myMap.put("6", "1");
System.out.println("HashMap before iterator: "+myMap);
Iterator<String> it1 = myMap.keySet().iterator();
while(it1.hasNext()){
String key = it1.next();
if(key.equals("3")) myMap.put(key+"new", "new3");
}
System.out.println("HashMap after iterator: "+myMap);
}
}
Output:
ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$KeyIterator.next(HashMap.java:828)
at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)
It’s clear from the output that ConcurrentHashMap takes care of the new entry in the map while iteration whereas HashMap throws ConcurrentModificationException
. Let’s look at the exception stack trace closely. The following statement has thrown Exception.
String key = it1.next();
It means that the new entry got inserted in the HashMap but Iterator is failing. Actually, Iterator on Collection objects is fail-fast i.e any modification in the structure or the number of entries in the collection object will trigger the exception.
We have taken the set of keys from HashMap and then iterating over it. HashMap contains a variable to count the number of modifications and iterator use it when you call its next() function to get the next entry. HashMap.java
:
/**
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient volatile int modCount;
Let’s change the code a little bit to come out of the iterator loop when we insert the new entry. All we need to do is add a break statement after the put call.
if(key.equals("3")){
myMap.put(key+"new", "new3");
break;
}
The output with the above code:
ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1}
What if we don’t add a new entry but update the existing key-value pair? Will it throw exception? Let’s change the code in the original program and check it out.
//myMap.put(key+"new", "new3");
myMap.put(key, "new3");
There won’t be any exception because the collection is modified but its structure remains the same.
Did you notice those angle brackets while creating our collection object and Iterator? It’s called generics and it’s very powerful when it comes to type-checking at compile time to remove ClassCastException at runtime. Learn more about generics in Java Generics Example. You should also read Java Collections Interview Questions and Iterator Design Pattern in Java.
You can checkout more Java collection examples from our GitHub Repository.
Reference: API Doc
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Java and Python Developer for 20+ years, Open Source Enthusiast, Founder of https://www.askpython.com/, https://www.linuxfordevices.com/, and JournalDev.com (acquired by DigitalOcean). Passionate about writing technical articles and sharing knowledge with others. Love Java, Python, Unix and related technologies. Follow my X @PankajWebDev
As a website resource for companies and engineering enthusiasts to comply with the newest and greatest breakthroughs in Unified Communications, IP Telephony, Hosted Communications and VoIP.
- internet
Odd behaviour, the result of the last modification comes out as HashMap after iterator: {3=new3, 2=1, 1=1, 6=1, 5=1, 4=1}
- Khalid
defnetly we get confused about Output. Can you Explain more reagarding the above Program…When we adding the element first time it provides an Exception…But When you have Written “Map.put(key, “new3”);” this line it doesnt provide any error.Explain it in better way…
- Ashok singh
Excellent! Clears the concept and the usage of ConcurrentHashMap Thanks
- Rajeev
I have added code to remove one item from map. the item is removed from map. But when its iterating it is printing the key and with value as null. Does that mean iterator has that key even though map does not have it? Does iterator will have a copy of keys? Below is modified code: while(it.hasNext()){ String key = it.next(); System.out.println("Key "+key+"value: "+myMap.get(key)); if(key.equals(“3”)) { myMap.put(key+“new”, “new3”); myMap.remove(“4”); System.out.println("while iterating: "+myMap); } } System.out.println("ConcurrentHashMap after iterator: "+myMap); ouput is: ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1} Key 1 value: 1 Key 5 value: 1 Key 6 value: 1 Key 3 value: 1 while iterating: {1=1, 3new=new3, 5=1, 6=1, 3=1, 2=1} Key 4 value: null Key 2 value: 1 ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 2=1}
- Sravanthi
For the key “4” : while(it1.hasNext()){ String key = it1.next(); if(key.equals(“4”)){ myMap.put(key+“new”, “new4”); } } Output: Got no ConcurrentModificationException occured… HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1} HashMap after iterator: {3=1, 2=1, 1=1, 4new=new4, 6=1, 5=1, 4=1} How???
- Nazeer Khan
Nicely explained. can you please tell why there is no exception when we are try to change the value but not key. //myMap.put(key+“new”, “new3”); myMap.put(key, “new3”); do we have seperate “modCount” for key and value in map. but how it is getting a updated value?
- Devendra
Nicely compiled article. Understood the concept quickly. Thank you.
- Ankit Tripathi
if u are breaking from while when key is 3 then how could it print the remaining values in while loop if(key.equals(“3”)){ myMap.put(key+“new”, “new3”); break; } ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1} ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1} HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1} HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1} The output should be ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1} ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1} HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1} HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3} Please clarify
- nikhil
The above example is good. I have tried to explain the same using multiple threads trying to add data to HashMap. https://www.javavisited.com/2014/04/internal-working-of-hashmap\_15.html and https://www.javavisited.com/2014/04/internal-working-of-concurrenthashmap.html Please check this website for a demo of what I have mentioned above. Please correct me if my understanding is wrong somewhere.
- Ganesh Rashinker
i had gone through so many web sites, but no one has given clear definition, but finally i got complete clarity on this point. thanks brother.
- nawaz
Excellent example about concurenthashmap and concurentmodified exception
- Ram
Really this tutorial is awesome. Thanks for sharing this. Regards, Chandu.
- Chandrasekhar G
every time when get a iterator .the operation underlying is : public Iterator iterator() { return new Itr(); } private class Itr implements Iterator { int expectedModCount = modCount; … } then every mutative operation , thr modcount will be modCount++; that’s why when modCount changed ,but expectedModCount was initialized when iterator(),and not changed after. if (modCount != expectedModCount) throw new ConcurrentModificationException();
- mr_rookie
Map hm= new ConcurrentHashMap(); hm.put(“1”,1); hm.put(“2”,2); hm.put(“3”,3); System.out.println(hm); Iterator it = hm.keySet().iterator(); while(it.hasNext()){ String key = it.next(); if(key.equals(“3”)) hm.put(“3”,4); } System.out.println(hm); System.out.println(“+++++++++++++++++++++++++++++++++++”); hm= new HashMap(); hm.put(“1”,1); hm.put(“2”,2); hm.put(“3”,3); System.out.println(hm); Iterator it1 = hm.keySet().iterator(); while(it.hasNext()){ String key = it1.next(); if(key.equals(“3”)) hm.put(“3”,4); } System.out.println(hm); O/P is //concurrent hash map {1=1, 2=2, 3=3} {1=1, 2=2, 3=4} +++++++++++++++++++++++++++++++++++ //hashmap {1=1, 2=2, 3=3} {1=1, 2=2, 3=3} *Note :- I am using java 8 . is cocncurrent HashpMap example is handeled
- Tejas
Hi , I have checked this example in our eclipse and it was working in HashMap class too . public class ConcurrentHashMapExample { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try{ HashMap map = new HashMap(); map.put(“One”, “I am one”); map.put(“Two”,“I am two”); System.out.println(“Map is returned in first”+map); Iterator itr= map.keySet().iterator(); while(itr.hasNext()){ String key=itr.next(); System.out.println(“Traversing value”+key); if(“One”.equals(key)) map.put(key+“OneOne”, “I am Eleven”); System.out.println(“Map is returned in last”+map); } } catch(Exception e){ e.printStackTrace(); } Output is : Map is returned in first{Two=I am two, One=I am one} Traversing valueTwo Map is returned in last{Two=I am two, One=I am one} Traversing valueOne Map is returned in last{OneOneOne=I am Eleven, Two=I am two, One=I am one} In case of remove the element from hashmap ,It will showing the exception .Kindly correct the logic here
- Vikas Kumar
Not getting output as HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1} After adding break after put in hashMap. it is as HashMap after iterator: {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}
- Anand Maheshwari
If we are updating existing key value pair,exception will not come. By using break statement inside if loop, ConcurrentModificationException is resolving. How it is happening by inserting simple break.
- Krishna
everybody comes here only everytime before the interview :)
- haider raza
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.