How can I fix Exception in thread "main" java.util.ConcurrentModificationException [duplicate] - java

This question already has an answer here:
Can anyone explain me over ConcurrentModificationException?
(1 answer)
Closed 9 years ago.
I have 2 HashMap<Integer,Point3D> objects names are positiveCoOrdinate and negativeCoOrdinates.
I am checking PositiveCoOrdinates with following condition.if it satisfies that corresponding point adding into negativeCoOrdinates and deleting from positiveCoOrdinates.
HashMap<Integer, Point3d> positiveCoOrdinates=duelList.get(1);
HashMap<Integer, Point3d> negativecoOrdinates=duelList.get(2);
//condition
Set<Integer> set=positiveCoOrdinates.keySet();
for (Integer pointIndex : set) {
Point3d coOrdinate=positiveCoOrdinates.get(pointIndex);
if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) {
negativecoOrdinates.put(pointIndex, coOrdinate);
positiveCoOrdinates.remove(pointIndex);
}
}
While adding,deleting time I am getting the following error.
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at PlaneCoOrdinates.CoordinatesFiltering.Integration(CoordinatesFiltering.java:167)
at PlaneCoOrdinates.CoordinatesFiltering.main(CoordinatesFiltering.java:179)
For my testing,I mention System.out.println(coOrdinate.x); statement inside If condition.it's working fine.
If I add 2 lines(What I mention above) inside If condition,it throwing error.
How can I fix this.
Thanks.

The easiest way is to make a copy of the keySet:
Set<Integer> set= new HashSet<Integer>(positiveCoOrdinates.keySet());
The problem occurs because you are modifing the positiveCoOrdinates while you are using an Iterator that iterates through the keys.
You can also refactor your code and use an iterator over the entry set. This would be a better approach.
Set<Entry<Integer, Point3d>> entrySet = positiveCoOrdinates.entrySet();
for (Iterator<Entry<Integer, Point3d>> iterator = entrySet.iterator(); iterator.hasNext();) {
Entry<Integer, Point3d> entry = iterator.next();
Point3d coOrdinate = entry.getValue();
if (coOrdinate.x > xMaxValue || coOrdinate.y > yMaxValue
|| coOrdinate.z > zMaxValue) {
Integer pointIndex = entry.getKey();
negativecoOrdinates.put(pointIndex, coOrdinate);
iterator.remove();
}
}

You can't remove() from iterated collection when using the enhanced for-each loop. The for-each loop uses Iterator<Integer> implicitly. The JavaDoc clearly states that
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.
The for-each loop creates an iterator internally and uses it to traverse the set. Then you change the structure of the set ... and the iterator has to fail. The thing is that you don't have access to the iterator's methods, so you have to use Iterator<Integer> explicitly. The generated traversing bytecode will be the same, the only difference being you being able to remove elements from the list as you traverse it.
Set<Integer> set = positiveCoOrdinates.keySet();
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext(); ) {
Integer pointIndex = iterator.next();
Point3d coOrdinate = positiveCoOrdinates.get(pointIndex);
if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) {
negativecoOrdinates.put(pointIndex, coOrdinate);
iterator.remove(pointIndex); // this line changed!
}
}
If you are not familiar with iterators and their function, see the Oracle tutorial on Collections:
An Iterator is an object that enables you to traverse through a
collection and to remove elements from the collection selectively, if
desired. You get an Iterator for a collection by calling its iterator()
method.
Note that Iterator.remove() is the only safe way to modify a
collection during iteration; the behavior is unspecified if the
underlying collection is modified in any other way while the iteration
is in progress.
Use Iterator instead of the for-each construct when you need to:
Remove the current element. The for-each construct hides the iterator, so you cannot call remove(). Therefore, the for-each
construct is not usable for filtering.

If you want to modify collection at run time, you need to use Iterator instead of enhanced for loop. Because enhanced for loop provide only read only functionality. Following is the Iterator example:
Iterator<Entity> iterator = collection.Iterator();
while(iterator.hasNext()){
//DO Your Stuff
iterator.remove(); // this function call remove the element from collection at run time
}

As it has been pointed out by René the reason for this very common issue is concurrent modification to a collection while it is being read by another.
You can use ConcurrentHashMap or collections like CopyOnWriteArrayLit, but beware that those approaches might be little bit expensive and simple changers to code to eliminate reading of the same collection while in a iteration will resolve this type of issues.

Related

Can I use many listIterators sequentially to mutate or remove list elements from an ArrayList in Java?

I am relying on list iterators to move through a list of characters. This is a single-threaded program and I use listIterator objects sequentially in 4 different methods. Each method has the same setup:
private void myMethod(ArrayList<Integer> input) {
ListIterator<Integer> i = input.listIterator();
while (i.hasNext()) {
Integer in = i.next();
if (in < 10)
i.remove();
else
i.set(in*in); // because its lucky
}
}
With this pattern, on the second iterator the following Exception is thrown:
java.util.ConcurrentModificationException
However, looking at the javadocs I don't see this Exception in the Exceptions thrown nor do I see a method to close the iterator after I am done. Am I using the listIterator incorrectly? I have to iterate over the same ArrayList multiple times, each time conditionally removing or mutating each element. Maybe there is a better way to iterate over the ArrayList and this use-case is not best solved by a ListIterator.
java docs for ListIterator
This is explained in the ArrayList javadoc, you are modifying the list with remove() and set() while using an Iterator:
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.
It’s hard to give diagnostic for a problem when the shown code clearly isn’t the code that produced the exception, as it doesn’t even compile. The remove method of Iterator doesn’t take arguments and the set method is defined on ListIterator, but your code declares the variable i only as Iterator.
A fixed version
private void myMethod(ArrayList<Integer> input) {
ListIterator<Integer> i = input.listIterator();
while (i.hasNext()) {
Integer in = i.next();
if (in < 10)
i.remove();
else
i.set(in*in);
}
}
would run without problems. The answer to your general question is that each modification invalidates all existing iterators, except the one used to make the modification when you did use an iterator for the modification and not the collection interface directly.
But in your code, there is only one iterator, which is only created and used for this one operation. As long as there is no overlapping use of iterators to the same collection, there is no problem with the invalidation. Iterators existing from previous operations are abandoned anyway and the iterators used in subsequent operations do not exist yet.
Still, it’s easier to use
private void myMethod(ArrayList<Integer> input) {
input.removeIf(in -> in < 10);
input.replaceAll(in -> in*in);
}
instead. Unlike the original code, this does two iterations, but as explained in this answer, removeIf will be actually faster than iterator based removal in those cases, where performance really matters.
But still, the problem persists. The shown code can’t cause a ConcurrentModificationException, so your actual problem is somewhere else and may still be present, regardless of how this one method has been implemented.
I am not knowledgable enough about Java ListIterators to answer the question but it appears I have run into the XY problem here. The problem seems to be better solved with Java Streams to remove the element or map the element into a new ArrayList by exercising a function on each element in the original ArrayList.
private ArrayList<Integer> myMethod(ArrayList<Integer> input) {
ArrayList<Integer> results = input.stream().filter(
in -> (in < 10)).collect(Collectors.toCollection(ArrayList::new));
results = input.stream().map(
in -> in*in).collect(Collectors.toCollection(ArrayList::new));
return results;
}

how to remove data from ArrayList [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.
In Java, is it legal to call remove on a collection when iterating through the collection using a foreach loop? For instance:
List<String> names = ....
for (String name : names) {
// Do something
names.remove(name).
}
As an addendum, is it legal to remove items that have not been iterated over yet? For instance,
//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
// Do something
while (names.remove(name));
}
To safely remove from a collection while iterating over it you should use an Iterator.
For example:
List<String> names = ....
Iterator<String> i = names.iterator();
while (i.hasNext()) {
String s = i.next(); // must be called before you can call i.remove()
// Do something
i.remove();
}
From the Java Documentation :
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.
Perhaps what is unclear to many novices is the fact that iterating over a list using the for/foreach constructs implicitly creates an iterator which is necessarily inaccessible. This info can be found here
You don't want to do that. It can cause undefined behavior depending on the collection. You want to use an Iterator directly. Although the for each construct is syntactic sugar and is really using an iterator, it hides it from your code so you can't access it to call Iterator.remove.
The behavior of an iterator is
unspecified if the underlying
collection is modified while the
iteration is in progress in any way
other than by calling this method.
Instead write your code:
List<String> names = ....
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String name = it.next();
// Do something
it.remove();
}
Note that the code calls Iterator.remove, not List.remove.
Addendum:
Even if you are removing an element that has not been iterated over yet, you still don't want to modify the collection and then use the Iterator. It might modify the collection in a way that is surprising and affects future operations on the Iterator.
for (String name : new ArrayList<String>(names)) {
// Do something
names.remove(nameToRemove);
}
You clone the list names and iterate through the clone while you remove from the original list. A bit cleaner than the top answer.
The java design of the "enhanced for loop" was to not expose the iterator to code, but the only way to safely remove an item is to access the iterator. So in this case you have to do it old school:
for(Iterator<String> i = names.iterator(); i.hasNext();) {
String name = i.next();
//Do Something
i.remove();
}
If in the real code the enhanced for loop is really worth it, then you could add the items to a temporary collection and call removeAll on the list after the loop.
EDIT (re addendum): No, changing the list in any way outside the iterator.remove() method while iterating will cause problems. The only way around this is to use a CopyOnWriteArrayList, but that is really intended for concurrency issues.
The cheapest (in terms of lines of code) way to remove duplicates is to dump the list into a LinkedHashSet (and then back into a List if you need). This preserves insertion order while removing duplicates.
I didn't know about iterators, however here's what I was doing until today to remove elements from a list inside a loop:
List<String> names = ....
for (i=names.size()-1;i>=0;i--) {
// Do something
names.remove(i);
}
This is always working, and could be used in other languages or structs not supporting iterators.
Yes you can use the for-each loop,
To do that you have to maintain a separate list to hold removing items and then remove that list from names list using removeAll() method,
List<String> names = ....
// introduce a separate list to hold removing items
List<String> toRemove= new ArrayList<String>();
for (String name : names) {
// Do something: perform conditional checks
toRemove.add(name);
}
names.removeAll(toRemove);
// now names list holds expected values
Make sure this is not code smell. Is it possible to reverse the logic and be 'inclusive' rather than 'exclusive'?
List<String> names = ....
List<String> reducedNames = ....
for (String name : names) {
// Do something
if (conditionToIncludeMet)
reducedNames.add(name);
}
return reducedNames;
The situation that led me to this page involved old code that looped through a List using indecies to remove elements from the List. I wanted to refactor it to use the foreach style.
It looped through an entire list of elements to verify which ones the user had permission to access, and removed the ones that didn't have permission from the list.
List<Service> services = ...
for (int i=0; i<services.size(); i++) {
if (!isServicePermitted(user, services.get(i)))
services.remove(i);
}
To reverse this and not use the remove:
List<Service> services = ...
List<Service> permittedServices = ...
for (Service service:services) {
if (isServicePermitted(user, service))
permittedServices.add(service);
}
return permittedServices;
When would "remove" be preferred? One consideration is if gien a large list or expensive "add", combined with only a few removed compared to the list size. It might be more efficient to only do a few removes rather than a great many adds. But in my case the situation did not merit such an optimization.
Those saying that you can't safely remove an item from a collection except through the Iterator aren't quite correct, you can do it safely using one of the concurrent collections such as ConcurrentHashMap.
Try this 2. and change the condition to "WINTER" and you will wonder:
public static void main(String[] args) {
Season.add("Frühling");
Season.add("Sommer");
Season.add("Herbst");
Season.add("WINTER");
for (String s : Season) {
if(!s.equals("Sommer")) {
System.out.println(s);
continue;
}
Season.remove("Frühling");
}
}
It's better to use an Iterator when you want to remove element from a list
because the source code of remove is
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
so ,if you remove an element from the list, the list will be restructure ,the other element's index will be changed, this can result something that you want to happened.
Use
.remove() of Interator or
Use
CopyOnWriteArrayList

Java concurrentmodificationexception in priority queue

I have a problem iterating my priority queue which cost Concurrentmodificationexception.
code for iterating:
Queue<Patient> pq = new PriorityQueue<Patient>();
Iterator<Patient> it = pq.iterator();
while(iter.hasNext()){
Patient current = iter.next();
if(current.getName().equals(patientName)){
pq.remove(p);
}
}
There error says that iter.next() cost Concurrentmodificationexception.
May i please know how to resolve this? i have search the internet but the still cant find a solution to this.
Change your code to following for solving it -
Queue<Patient> pq = new PriorityQueue<Patient>();
Iterator<Patient> iter = pq.iterator();
while(iter.hasNext()){
Patient current = iter.next();
if(current.getName().equals(patientName)){
iter.remove();
}
}
Explanation ConcurrentModificationException is thrown from next() method of iterator, if there is any structural change in the underlying collection (in your case Queue) i.e. any element is added or removed in the queue directly. It is called Fail Fast Iterator.
Try to use ConcurrentLinkedQueue instead of PriorityQueue
Acording to: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html
Beware that, unlike in most collections, the size method is NOT a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires a traversal of the elements, and so may report inaccurate results if this collection is modified during traversal.
Since Java8, you can remove using removeIf which is part of Collection contract.
Given that removeIf method takes a predicate, your code could be as simple as :
priorityQueue.removeIf(patient -> patient.getName().equals(patientName));
As for the Concurrent exception you had, this simply happened because you tried to remove calling PriorityQueue#remove directly while you were already iterating which would make the iterator obsolete. The proper way to remove when iterating is by using Iterator#next and then Iterator#remove (this is actually what de default implementation of removeIf does).

Unconventional use of Iterator to iterate over a collection

I am aware of the conventional iterator creation-usage for a List<String> list as below:
//Conventional-style
Iterator<String> iterator = list.iterator()
while(iterator.hasNext()){
String string = iterator.next();
//...further code goes here
}
However, in the accepted answer of Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop, I came across this unusual for loop usage with Iterator:
//Unconventional for loop style
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String string = iterator.next();
//...further code goes here
}
Now, I'd like to know:
Does this unconventional style create the iterator on the collection for each iteration over and over again? Or is it somehow a special kind of intelligent for-loop, which creates the iterator once and reuses it?
If it creates an iterator each time, shouldn't it be a performance concern?
Can we replace the while loop line in the conventional style with
for(;iterator.hasNext();), if I were to use a for loop only?
PS: I am well aware of the enhanced for loop use on a collection. I am looking at this with the intention of 'safe' removal of elements, without causing a ConcurrentModificationException.
The idiom you call "unconventional" is actually the recommended one because it restricts the scope of the iterator variable to the loop where it is used.
The iterator is created once, before the loop begins. This follows from the general semantics of the for loop, which I warmly advise you get acquainted with.
You can, but you would not be recommended to. Such an idiom would be a pointless obfuscation of the while idiom.
Finally, note that for 99% of use cases all of the above is moot because you really should be using either the enhanced for loop or Java 8 forEach.
Java is derived from C, and thus for (A; B; C) { P; } has the same semantics as A; while (B) { P; C; }. The only difference is the scope of the variables. In particular, the A part is only executed once. So your two code examples do exactly the same, but in the for-variant the scope of the variable is restricted.
The more modern way of iterating through a collection is the enhance for loop:
for (String string : list) {
...
}
However, if you want to delete or change items while iterating through it, you still need the iterator version. For example:
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String string = it.next();
if (someFunction(string)) {
it.delete();
}
}
has no enhanced for-loop equivalent.
1.
No, it does not create an iterator over and over again.. This was the perfectly fine style before Java included the interface Iterable<T>.
If you want to remove an item while iterating over the collection you have to use the iterator.remove() method if it is provided.. Because otherwise a ConcurrentModificationException will be thrown.
If you do not want to remove an Item while iterating over the collection then you should just use the for each concept, which is provided by every collection that implements the Iterable<T> interface. (link in the end for more information)
for (String s : yourList) {
... // do something with the string
}
2.
Yes!! Use the for loop idiom. But as I said, if you do not want to use the iterator.remove() operation, but just want to iterate over the collection, you should use the provided for each concept.
You can find a lot of information on the downsides of the iterator.next() approach here and why the newly integrated for:each concept is better:
https://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

fail-fast iterator

I get this definition : As name suggest fail-fast Iterators fail as soon as they realized that structure of Collection has been changed since iteration has begun.
what it mean by since iteration has begun? is that mean after Iterator it=set.iterator() this line of code?
public static void customize(BufferedReader br) throws IOException{
Set<String> set=new HashSet<String>(); // Actual type parameter added
**Iterator it=set.iterator();**
First of all, they are fail-fast, not fail-safe.
The contract is that structural modifications (i.e. insertions/deletions) of certain types of collections invalidate existing iterators into the collection. Fail-fast iterators attempt to detect that they are not supposed to be valid and throw a ConcurrentModificationException. This is done as a service to you, the programmer, to help discover this type of bugs quicker.
In your example:
Iterator it = set.iterator();
it.next();
set.add("unique-entry"); // invalidates the iterator
it.next();
If you're lucky, the second it.next() will detect the invalid usage and throw an exception. Note that this is done on a best-effort basis and is not guaranteed.
is that mean after Iterator it=set.iterator() this line of code?
Yes. If you look at the code for HashSet.iterator() you'll see it's just this:
return map.keySet().iterator();
... which delegate's to HashMap.KeySet.iterator(). There are a few more links in the chain, but eventually you get to HashMap.HashIterator, which contains this in the constructor:
private abstract class HashIterator<E> implements Iterator<E> {
int expectedModCount; // For fast-fail
...
HashIterator() {
expectedModCount = modCount;
...
}
}
... where modCount is a field in the enclosing instance of HashMap which keeps track of the number of modifications.
The iterator being fail-fast means the following piece of code is expected to fail:
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
set.add("");
it.next(); // the set has changed now, and the iterator will throw an exception
because the following series of events occur: The iterator is created, then its underlying collection changes, then the iterator is accessed.
yes, don't change the collection after using .iterator() if you are planning to iterate over it , you can use the .remove() if you want to remove the latest element though
Before Fail Fast Iterator is starting to work it’s getting count of collection and after any iteration it is checking if count is changed or not, and in case of changed count JVM will throw ConcurrentModificationException. Fail fast iterators are any iterator of collection which is inside java.util package(e.g. ArrayList, LinkedList etc) and Fail Safe iterators are iterators which are inside of java.concurrent package(e.g. CopyOnWriteArrayList, CopyOnWriteSet etc.). Fail Fast iterators will throw exception in case of concurrent modification but Fail Safe iterator is basically working with copy of collection which is not throwing exception in case of concurrent modification.

Categories