object names positiveCoOrd...">

How to fix an exception in the stream "main" java.util.ConcurrentModificationException

I have 2 HashMap<Integer,Point3D> object names positiveCoOrdinate and negativeCoOrdinates .

I check PositiveCoOrdinates following condition. If it satisfies that the corresponding point is added to negativeCoOrdinates and removed 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); } } 

When adding, deleting time, I get 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 the statement System.out.println(coOrdinate.x); inside If condition.it working fine.

If I add 2 lines (as I mention above) inside the If condition, it throws an error.

How can I fix this.

Thanks.

+6
source share
4 answers

The easiest way is to make a copy of keySet:

  Set<Integer> set= new HashSet<Integer>(positiveCoOrdinates.keySet()); 

The problem is due to the modification of positiveCoOrdinates when you use an Iterator that iterates with the keys.

You can also reorganize your code and use an iterator over a set of records. This will be the best 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(); } } 
+11
source

You cannot remove() from an iterated collection when using the extended for-each loop. The for-each loop uses an Iterator<Integer> implicitly. JavaDoc clearly states that

The iterators returned by the collection methods "class view" class are unsuccessful: if the map is structurally modified at any time after creating the iterator, in any way, except for the iterator's own remove() method, the iterator will throw a ConcurrentModificationException . Thus, in the face of parallel modifications , the iterator crashes quickly and cleanly, and not at the risk of arbitrary, non-deterministic behavior at an undefined time in the future.

The for-each loop creates an iterator inside and uses it to move around the set. Then you change the structure of the set ... and the iterator should fail. The point is that you do not have access to iterator methods, so you must explicitly use Iterator<Integer> . The generated byte bytecode will be the same, with the only difference being that you can remove items from the list when you move 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 functions, see the Oracle collections tutorial :

An Iterator is an object that allows you to go through collections and selectively remove items from the collection, if desired. You get an Iterator for the collection by calling its iterator() method.

Note that Iterator.remove() is the only safe way to change the collection during iteration; behavior is unspecified if the base collection is modified in any other way while the iteration is Running.

Use an Iterator instead of a for-each construct when you need to:

  • Delete current item. The for-each construct hides the iterator, so you cannot call remove() . Therefore, the for-each construct is not used for filtering.
+2
source

If you want to change the collection at run time, you need to use Iterator instead of extended for loop. Because advanced for loop provides read-only functions. The following is an example of an Iterator:

 Iterator<Entity> iterator = collection.Iterator(); while(iterator.hasNext()){ //DO Your Stuff iterator.remove(); // this function call remove the element from collection at run time } 
0
source

As Rene noted, the cause of this very common problem is the simultaneous modification of the collection when it is being read by another.

You can use ConcurrentHashMap or collections such as CopyOnWriteArrayLit , but be careful that these approaches can be a bit expensive and simple code changers to prevent reading of the same collection, while iterating this will solve the type of problems.

0
source

Source: https://habr.com/ru/post/955014/


All Articles