How to handle ConcurrentModificationException while removing items in collection? [duplicate] - java

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 am trying delete a String that occurs 5 times in my List. This is what I've tried:
for(String obj : list1)
{
if(new ArzList().countOccurrence(list1, obj ) == 5)
{
list2.add(obj);
list1.removeAll(Collections.singleton(obj));
}
else{
list3.add(obj);
list1.removeAll(Collections.singleton(obj));
}
}
But I get java.util.ConcurrentModificationException each time.
How do I solve it?

You shouldn't iterate and remove through the same list.
Create a copy of the original list. Iterate through the original list but remove items from the copy version. Return the duplicate(copy) version of the list.

You're not allowed to modify the data structure mid-way through an iterator.
You could just use a normal loop here:
for (int i = 0; i < list1.size(); i++) {
String obj = list1.get(i);
...
}

You can only safely delete an element during a loop from a collection using the Iterator.
Iterator<String> myIterator = list1.iterator();
while(myIterator.hasNext()) {
//add logic to search list and delete element here
}

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

Iterating through collection. What are the differences? [duplicate]

This question already has answers here:
Is there a performance difference between a for loop and a for-each loop?
(16 answers)
Closed 9 years ago.
If we have 2 ways to iterate :
First :
Object ob;
ArrayList<Obect> list;
for(int i=0;i<list.size();i++)
{ //Todo}
Second :
Object ob;
ArrayList<Obect> list;
for(Object o:list)
{ //Todo}
So what are the differences ? I found that in second case , if try to remove object in this cycle , I get a concurrent modification exception.
In your first example, you are iterating through the list yourself. You must take responsibility for maintaining the state of your iteration if you modify the collection during iteration.
In your second example, the "foreach" loop you are using uses an implicit Iterator behind the scenes. If you modify the collection yourself with an active Iterator, you will get a ConcurrentModificationException.
If you must remove an element while using an Iterator, then use an explicit Iterator:
for(Iterator<Object> itr = list.iterator(); itr.hasNext())
{
Object o = itr.next():
if (decideToRemove)
itr.remove();
}
The Iterator's remove operation is allowed to remove an element without throwing a ConcurrentModificationException.
The proper way to remove from collections is to use a 3rd kind of loop that looks like this:
for (Iterator<Object> iterator = new ArrayList<>().iterator(); iterator.hasNext(); ) {
Object o = iterator.next();
if (someCondition())
iterator.remove();
}

"java.util.ConcurrentModificationException" while removing some objects from a list [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 9 years ago.
I need to delete some objects from a list if they meet a condition.
But I am getting java.util.ConcurrentModificationException.
Here is my code:
collegeList.addAll(CollegeManager.findByCollegeID(stateCode, districtCode));
for(College clg:collegeList){
if(!clg.approve()){
collegeList.remove(clg);
}
}
You can't remove elements while iterating through them in that manner. Use an Iterator instead.
Iterator<College> iter = collegeList.iterator();
while(iter.hasNext()) {
College clg = iter.next();
if(!clg.approve()) {
iter.remove();
}
}
You need to use an Iterator to iterate through List and remove objects using Iterator#remove().

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