Java - Exception in thread "main" java.util.ConcurrentModificationException - java

Is there any way I can modify the HashMap values of a particular key while iterating over it?
A sample program is given below:
public static void main(String[] args) {
HashMap<Integer,ArrayList<String>> hm = new HashMap<Integer, ArrayList<String>>();
ArrayList<String> ar = new ArrayList<String>();
for(int i=0;i<50;i++){
ar.add(Integer.toString(i));
}
hm.put(1, ar);
for(String s:hm.get(1)){
hm.get(1).add("hello");
}
}
Error Thrown:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Excp.main(Excp.java:17)

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
Below peice of code is causing the problem.
for(String s:hm.get(1)){
hm.get(1).add("hello");
}
You are iterating and modifying the same. Avoid this by creating new ArrayList
ArrayList<String> ar1 = new ArrayList<String>();
for (String s : hm.get(1)) {
ar1.add("hello");
}
have a read here

When we are trying to modify collection object while iterating then we get this exception. Check following code:
for(String str : stringList){
stringList.add("Test");
}
So in above we get runtime exception.
Solution
Use iterator over For-Each loop, like:
static void filter(Collection<?> c) {
for (Iterator<?> it = c.iterator(); it.hasNext(); )
if (!anyCondition(it.next()))
it.remove();
}
So basic difference between For-Each and iterator is, we can modify collection while iterating using only iterator.

The problem in the code your presented isn't modifying the HashMap, it's modifying the ArrayList while iterating it.
You can avoid this exception if you use ar's ListIterator instead of using an enhanced for loop:
for (ListIterator<String> i = ar.listIterator(); i.hasNext(); i.next()) {
i.add("hello");
}

If try to modify while iterating your list you will get this Exception.
for(String s:hm.get(1)){ // iterate
hm.get(1).add("hello");//modify
}
Both operation affect to hm
You don't need to iterate here. Just use
hm.get(1).add("hello");

If you want to add to the original ArrayList, then iterate through it on your own:
final ArrayList<String> arr = hm.get(1);
final int size = arr.size();
// this will add size number of "hello" strings to ArrayList arr
for(int i = 0; i < size; ++i){
// you don't appear to ever use this value
final String s = arr.get(i);
// do something to arr
arr.add("hello");
}

Although not related to the question, but just adding
ConcurrentModificationException can also occur if you get the iterator over a collection first and then add some more elements over it and then iterating over the collection will throw this exception.
For example :
package got;
import java.util.*;
public class GotCharacters {
public static void main(String... args){
Person p1 = new Person("TL", 40, "Tyrion Lannister");
Person p2 = new Person("JM", 50, "Jorah Mormont");
Person p3 = new Person("AS", 20, "Arya Stark");
//Defining the collection and adding some elements
ArrayList<Person> al;
al = new ArrayList<Person>();
al.add(p1);
al.add(p2);
al.add(p3);
//Getting the iterator
Iterator<Person> itr = al.iterator();
Royalty r1 = new Student("DT", 25, "Daenerys Targaryen", "DragonMother", "Targaryen");
Royalty r2 = new Student("JS", 28, "Jon Snow", "Lord Commander", "Targaryen");
Collection<Royalty> c = new ArrayList<Royalty>();
c.add(s1);
c.add(s2);
//Adding more elements after getting the iterator
al.addAll(c);
while(itr.hasNext()){
System.out.print(itr.next());
}
}
}
Outcome :
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at myArrayList.ArrayList1.main(ArrayList1.java:34)

Concurrent Modification in programming means to modify an object concurrently when another task is already running over it. Fail Fast And Fail Safe Iterators in Java
Iterators in java are used to iterate over the Collection objects. Fail-Fast iterators immediately throw ConcurrentModificationException if there is structural modification of the collection. Fail-Safe iterators don’t throw any exceptions if a collection is structurally modified while iterating over it. This is because, they operate on the clone of the collection, not on the original collection and that’s why they are called fail-safe iterators.
Please use ConcurrentHashMap if you want to modify in between.

If you can use normal(Iterating over indexes) for loop you can avoid that error.

Related

Using only nested loops, if-else statements, and ArrayList methods, how do I locate and remove duplicate values in an ArrayList (Java)? [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 8 years ago.
I'm trying to remove some elements from an ArrayList while iterating it like this:
for (String str : myArrayList) {
if (someCondition) {
myArrayList.remove(str);
}
}
Of course, I get a ConcurrentModificationException when trying to remove items from the list at the same time when iterating myArrayList. Is there some simple solution to solve this problem?
Use an Iterator and call remove():
Iterator<String> iter = myArrayList.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (someCondition)
iter.remove();
}
As an alternative to everyone else's answers I've always done something like this:
List<String> toRemove = new ArrayList<String>();
for (String str : myArrayList) {
if (someCondition) {
toRemove.add(str);
}
}
myArrayList.removeAll(toRemove);
This will avoid you having to deal with the iterator directly, but requires another list. I've always preferred this route for whatever reason.
Java 8 user can do that: list.removeIf(...)
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
list.removeIf(e -> (someCondition));
It will remove elements in the list, for which someCondition is satisfied
You have to use the iterator's remove() method, which means no enhanced for loop:
for (final Iterator iterator = myArrayList.iterator(); iterator.hasNext(); ) {
iterator.next();
if (someCondition) {
iterator.remove();
}
}
No, no, NO!
In single threated tasks you don't need to use Iterator, moreover, CopyOnWriteArrayList (due to performance hit).
Solution is much simpler: try to use canonical for loop instead of for-each loop.
According to Java copyright owners (some years ago Sun, now Oracle) for-each loop guide, it uses iterator to walk through collection and just hides it to make code looks better. But, unfortunately as we can see, it produced more problems than profits, otherwise this topic would not arise.
For example, this code will lead to java.util.ConcurrentModificationException when entering next iteration on modified ArrayList:
// process collection
for (SomeClass currElement: testList) {
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
}
}
But following code works just fine:
// process collection
for (int i = 0; i < testList.size(); i++) {
SomeClass currElement = testList.get(i);
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
i--; //to avoid skipping of shifted element
}
}
So, try to use indexing approach for iterating over collections and avoid for-each loop, as they are not equivalent!
For-each loop uses some internal iterators, which check collection modification and throw ConcurrentModificationException exception. To confirm this, take a closer look at the printed stack trace when using first example that I've posted:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at TestFail.main(TestFail.java:43)
For multithreading use corresponding multitask approaches (like synchronized keyword).
While other suggested solutions work, If you really want the solution to be made thread safe you should replace ArrayList with CopyOnWriteArrayList
//List<String> s = new ArrayList<>(); //Will throw exception
List<String> s = new CopyOnWriteArrayList<>();
s.add("B");
Iterator<String> it = s.iterator();
s.add("A");
//Below removes only "B" from List
while (it.hasNext()) {
s.remove(it.next());
}
System.out.println(s);
If you want to modify your List during traversal, then you need to use the Iterator. And then you can use iterator.remove() to remove the elements during traversal.
List myArrayList = Collections.synchronizedList(new ArrayList());
//add your elements
myArrayList.add();
myArrayList.add();
myArrayList.add();
synchronized(myArrayList) {
Iterator i = myArrayList.iterator();
while (i.hasNext()){
Object object = i.next();
}
}
One alternative method is convert your List to array, iterate them and remove them directly from the List based on your logic.
List<String> myList = new ArrayList<String>(); // You can use either list or set
myList.add("abc");
myList.add("abcd");
myList.add("abcde");
myList.add("abcdef");
myList.add("abcdefg");
Object[] obj = myList.toArray();
for(Object o:obj) {
if(condition)
myList.remove(o.toString());
}
You can use the iterator remove() function to remove the object from underlying collection object. But in this case you can remove the same object and not any other object from the list.
from here

Removing elements from array in java throws exception [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 8 years ago.
I'm trying to remove some elements from an ArrayList while iterating it like this:
for (String str : myArrayList) {
if (someCondition) {
myArrayList.remove(str);
}
}
Of course, I get a ConcurrentModificationException when trying to remove items from the list at the same time when iterating myArrayList. Is there some simple solution to solve this problem?
Use an Iterator and call remove():
Iterator<String> iter = myArrayList.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (someCondition)
iter.remove();
}
As an alternative to everyone else's answers I've always done something like this:
List<String> toRemove = new ArrayList<String>();
for (String str : myArrayList) {
if (someCondition) {
toRemove.add(str);
}
}
myArrayList.removeAll(toRemove);
This will avoid you having to deal with the iterator directly, but requires another list. I've always preferred this route for whatever reason.
Java 8 user can do that: list.removeIf(...)
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
list.removeIf(e -> (someCondition));
It will remove elements in the list, for which someCondition is satisfied
You have to use the iterator's remove() method, which means no enhanced for loop:
for (final Iterator iterator = myArrayList.iterator(); iterator.hasNext(); ) {
iterator.next();
if (someCondition) {
iterator.remove();
}
}
No, no, NO!
In single threated tasks you don't need to use Iterator, moreover, CopyOnWriteArrayList (due to performance hit).
Solution is much simpler: try to use canonical for loop instead of for-each loop.
According to Java copyright owners (some years ago Sun, now Oracle) for-each loop guide, it uses iterator to walk through collection and just hides it to make code looks better. But, unfortunately as we can see, it produced more problems than profits, otherwise this topic would not arise.
For example, this code will lead to java.util.ConcurrentModificationException when entering next iteration on modified ArrayList:
// process collection
for (SomeClass currElement: testList) {
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
}
}
But following code works just fine:
// process collection
for (int i = 0; i < testList.size(); i++) {
SomeClass currElement = testList.get(i);
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
i--; //to avoid skipping of shifted element
}
}
So, try to use indexing approach for iterating over collections and avoid for-each loop, as they are not equivalent!
For-each loop uses some internal iterators, which check collection modification and throw ConcurrentModificationException exception. To confirm this, take a closer look at the printed stack trace when using first example that I've posted:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at TestFail.main(TestFail.java:43)
For multithreading use corresponding multitask approaches (like synchronized keyword).
While other suggested solutions work, If you really want the solution to be made thread safe you should replace ArrayList with CopyOnWriteArrayList
//List<String> s = new ArrayList<>(); //Will throw exception
List<String> s = new CopyOnWriteArrayList<>();
s.add("B");
Iterator<String> it = s.iterator();
s.add("A");
//Below removes only "B" from List
while (it.hasNext()) {
s.remove(it.next());
}
System.out.println(s);
If you want to modify your List during traversal, then you need to use the Iterator. And then you can use iterator.remove() to remove the elements during traversal.
List myArrayList = Collections.synchronizedList(new ArrayList());
//add your elements
myArrayList.add();
myArrayList.add();
myArrayList.add();
synchronized(myArrayList) {
Iterator i = myArrayList.iterator();
while (i.hasNext()){
Object object = i.next();
}
}
One alternative method is convert your List to array, iterate them and remove them directly from the List based on your logic.
List<String> myList = new ArrayList<String>(); // You can use either list or set
myList.add("abc");
myList.add("abcd");
myList.add("abcde");
myList.add("abcdef");
myList.add("abcdefg");
Object[] obj = myList.toArray();
for(Object o:obj) {
if(condition)
myList.remove(o.toString());
}
You can use the iterator remove() function to remove the object from underlying collection object. But in this case you can remove the same object and not any other object from the list.
from here

Old for-each loop works, new for-each loop gets ConcurrentModificationException

From what I've read I understand that you get a ConcurrentModificationException when you try to edit a list while it's still being iterated.
Now what I don't get is, why does the old foreach loop not give the exception while the the new foreach loop does?
public void newForeachLoop() {
for (Person person : list) {
if (person.getPosition().equals(this.getPosition())) {
list.remove(person);
}
}
}
public void oldForeachLoop() {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getPosition().equals(this.getPosition())) {
list.remove(list.get(i));
}
}
}
In the old loop you're not using the lists iterator instead you're using a count of the objects in the list.
In the new loop you're using the built-in iterator which is a pointer for that instance. When you remove an item from the list you're modifying that instance and resetting the iterator thus throwing the exception.
Because for each loop is iterator based, you can't just remove an element from the list while iterating over it.
You can even try explicitly using iterator and removing an element.
List<String> list= new ArrayList <String>;
list.add("One");
list.add("two");
list.add("three");
Iterator listItr = list.iterator () ;
while ( listItr.hasNext() )
{
String countStr = itr.next();
if ( countStr.equals ("two"))
itr.remove(); //will not throw any exception
//if you do it list.remove (countStr) //will throw exception
}
Removing an element from list using index while iterating over it, will definitely not throw any exception but you need to be extra careful about its length getting modified. Even indexes of further elements are also disturbed by your operation. So if you take care of this its not a problem.
As #SacJn explained, you cannot make structural changes in the List (e.g. add or remove elements) while iterating it via iterator(). The iterator() will detect the inconsistency and throw a ConcurrentModificationException. In Java-8 there's clean and safe way to solve your task:
public void java8Solution() {
list.removeIf(person -> person.getPosition().equals(this.getPosition()));
}

CopyOnArrayList Concurrent modification

When we run above program, we get java.util.ConcurrentModificationException as soon as the ArrayList is modified. It happens because ArrayList iterator is fail-fast by design. What it means is that once the iterator is created, if the ArrayList is modified, it throws a ConcurrentModificationException.
public class ConcurrentListExample {
public void someMethod() {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
// get the iterator
Iterator<String> it = list.iterator();
//manipulate list while iterating
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
if (str.equals("2")) {
list.remove("5");
}
if (str.equals("3")) {
list.add("3 found");
}
if(str.equals("4")) {
list.set(1, "4");
}
}
}
}
but if we take Employee class:
public class Test {
public static void main(String[] args) {
List al = new ArrayList();
Employee ee = new Employee(1, "anoj");
Employee ee1 = new Employee(2, "hai");
al.add(ee);
al.add(ee1);
Iterator it = al.iterator();
while (it.hasNext()) {
Employee hh = (Employee)it.next();
if (hh.getName().equals("anoj")) {
al.remove(0);
System.out.println(al);
}
}
}
}
I didn't get a ConcurrentModificationException.
You can't modify and print operations simultaneously using iterator.
it support add() and remove().
It doesn't fail on the second time because the iterator returns anoj last. So hasNext returns false and next is never called, thus no ConcurrentModificationException.
Simply move the addition of ee1 above ee and it will fail
Note This is internal implementation to ArrayList as to 1. Why anoj is returned last and 2. Why hasNext doesnt throw CME.
The check for concurrent modification exception gas a flaw that if you remove the second last element of an ArrayList it wont complain but will skip the last entry.
this happens because it checks whether it has iterated size() times before checking the concurrent modification.
I think the correct explanation is this extract from th javadocs of ConcurrentModificationExcetion:
Note that fail-fast behavior cannot be guaranteed as it is, generally
speaking, impossible to make any hard guarantees in the presence of
unsynchronized concurrent modification. Fail-fast operations throw
ConcurrentModificationException on a best-effort basis. Therefore, it
would be wrong to write a program that depended on this exception for
its correctness: ConcurrentModificationException should be used only
to detect bugs.

Why ConcurrentModificationException in ArrayList? [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 4 years ago.
why following code throwing ConcurrentModificationException? Josh Bloch can avoid ConcurrentModificationException.
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
for(Integer field : list) {
list.remove(field);
list.add(200);
}
You can't use remove on the list while using the "for each" loop. Instead, you can use this to call remove on the iterator:
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
Integer integer = iterator.next();
// ...check if you want to remove this one...
iterator.remove();
}
If you actually want to replace every value with "200", or replace with some other value, it might make more sense to build up a new list:
List<Integer> newList = new ArrayList<Integer>();
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
Integer integer = iterator.next();
newList.add(integer);
iterator.remove();
}
It's unclear what the behavior should be if you're iterating over an array while modifying it.
What if you remove an element, should it still be iterated over?
Rather than trying to guess, the list throws a ConcurrentModificationException to cause an error rather than pass with unexpected behavior.
One solution is that you could iterate over a shallow copy of the list, and then modify the original list
You can remove objects from the ArrayList which you are using. I use this in my game engine and it works.
See http://code.google.com/p/game-engine-for-java/source/browse/src/com/gej/map/Map.java#350
for (int i = 0; i < objects.size(); i++) {
GObject other = objects.get(i);
if (other.isAlive()) {
// Update it
} else {
// Else remove it
objects.remove(i);
}
}
What the error you are having is this does not work for the for each loop. Try in a normal for loop and that should solve your problem.
Change your code to this.
ArrayList<Integer> list =new ArrayList<Integer>();
ArrayList<Integer> remove = new ArrayList<Integer>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
// Mark to remove
for (int i=0; i<list.size(); i++){
remove.add(list.get(i));
}
list.removeAll(remove);
remove.clear();
// adding 200 at the end because if added in the loop,
// it removes the 200 and adds every loop which causes
// unnecessary memory usage.
list.add(200);

Categories