Concurrent Modification Exception

How to avoid ConcurrentModificationException while removing elements from `ArrayList` while iterating it?

Use an Iterator and call remove():

Iterator<String> iter = myArrayList.iterator();

while (iter.hasNext()) {
String str = iter.next();

if (someCondition)
iter.remove();
}

java.util.ConcurrentModificationException thrown when adding to List

The ConcurrentModificationException is thrown when calling String value = it.next();. But the actual culprit is list.add("6");. You mustn't modify a Collection while iterating over it directly. You are using it.remove(); which is fine, but not list.add("6");.

While you can solve the problem with Streams, I will first offer a solution with Iterators, as this is a good first step for understanding the problem.

You need a ListIterator<String> if you want to add and remove during iteration:

for (ListIterator<String> it = list.listIterator(); it.hasNext();){
String value = it.next();

if (value.equals("4")) {
it.remove();
it.add("6");
}

System.out.println("List Value: " + value);
}

This should do the trick!


A solution using Streams:

List<String> newList = list.stream()
.map(s -> s.equals("4") ? "6" : s)
.collect(Collectors.toList());

Here we create a Stream from your List. We map all values to themselves, only "4" gets mapped to "6" and then we collect it back into a List. But caution, newList is immutable!

ConcurrentModificationException for ArrayList

You can't remove from list if you're browsing it with "for each" loop. You can use Iterator. Replace:

for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}

With:

for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext(); ) {
DrugStrength aDrugStrength = it.next();
if (!aDrugStrength.isValidDrugDescription()) {
it.remove();
}
}

Concurrent Modification Exception in Callable class

public MyCallable (List<Instance> instances) {
this.instances = Collections.synchronizedList(instances);
}

Using synchronizedList like this doesn't help you in the way you think it might.

It's only useful to wrap a list in a synchronizedList at the time you create it (e.g. Collections.synchronizedList(new ArrayList<>()). Otherwise, the underlying list is directly accessible, and thus accessible in an unsynchronized way.

Additionally, synchronizedList only synchronizes for the duration of individual method calls, not for the whole time while you are iterating over it.

The easiest fix here is to take a copy of the list in the constructor:

    this.instances = new ArrayList<>(instances);

Then, nobody else has access to that list, so they can't change it while you are iterating it.

This is different to taking a copy of the list in the call method, because the copy is done in a single-threaded part of the code: no other thread can be modifying it while you are taking that copy, so you won't get the ConcurrentModificationException (you can get a CME in single-threaded code, but not using this copy constructor). Doing the copy in the call method means the list is iterated, in exactly the same way as with the for loop you already have.

ConcurrentModificationException when using stream with Maps key set

@Eran already explained how to solve this problem better. I will explain why ConcurrentModificationException occurs.

The ConcurrentModificationException occurs because you are modifying the stream source. Your Map is likely to be HashMap or TreeMap or other non-concurrent map. Let's assume it's a HashMap. Every stream is backed by Spliterator. If spliterator has no IMMUTABLE and CONCURRENT characteristics, then, as documentation says:

After binding a Spliterator should, on a best-effort basis, throw ConcurrentModificationException if structural interference is detected. Spliterators that do this are called fail-fast.

So the HashMap.keySet().spliterator() is not IMMUTABLE (because this Set can be modified) and not CONCURRENT (concurrent updates are unsafe for HashMap). So it just detects the concurrent changes and throws a ConcurrentModificationException as spliterator documentation prescribes.

Also it worth citing the HashMap documentation:

The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

While it says about iterators only, I believe it's the same for spliterators.

Why im not getting concurrent modification exception during update of collection element?

why updating should cause concurrent modification?

If by "updating" you mean calling the set method, it won't cause concurrent modification.
Setting the value of an element in the List is not a structural modification, and therefore doesn't cause ConcurrentModificationException when performed during iteration.

Quotes from the ArrayList Javadoc:

A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification
...

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Concurrent Modification Exception : adding to an ArrayList

ConcurrentModificationException occurs when you modify the list (by adding or removing elements) while traversing a list with Iterator.

Try

List<Element> thingsToBeAdd = new ArrayList<Element>();
for(Iterator<Element> it = mElements.iterator(); it.hasNext();) {
Element element = it.next();
if(...) {
//irrelevant stuff..
if(element.cFlag){
// mElements.add(new Element("crack",getResources(), (int)touchX,(int)touchY));
thingsToBeAdd.add(new Element("crack",getResources(), (int)touchX,(int)touchY));
element.cFlag = false;
}
}
}
mElements.addAll(thingsToBeAdd );

Also you should consider enhanced for each loop as Jon suggested.

ConcurrentModificationException in LinkedList

The ConcurrentModificationException is usually thrown when iterating through the list and in the same time usually another thread or even the same loop tries to modify (add / remove) the contents of the list.



Related Topics



Leave a reply



Submit