Search code examples
javaconcurrentmodification

Need help modifying list based on comparison values (ConcurrentModification)


I am trying to see what possibility there is for something (don't tell me there isn't, this is my failed project) throughout an arrangement of points and their distances.

for (Point p1 : results) {
    remove.clear();
    for (Point p2 : results) {
        if (Math.sqrt(
            Math.pow(p1.getX() - p2.getX(), 2)
            + Math.pow(p1.getY() - p2.getY(), 2)
        ) % 1 > 0) {
            results.remove(p2);
        }
    }
}

Basically, I am trying to check if two points have an integer distance, and, if not, remove it from the set, and do this for all points (that remain).

However, I am getting a ConcurrentModificationException and I am not certain how to refactor it to accomplish the same task without just provoking the error in another way.

Are there any ways around this or is it just a limitation of Java?

EDIT: While the duplicate suggested link offers insight, the answers' focus on single loops has berth of excess that is not applicable. If this question is duplicate, it's on premise of that using an Iterator is just the answer.


Solution

  • Some Collection implementations use a "fail-fast" iterator. When removing an item from a Collection directly (using Collection#remove) while iterating over it will cause that exception.

    Enhanced for-loops uses the collection's iterator to iterate through the collection.

    You could change your enhanced loops to regular for loops:

    for(int i = 0; i < results.size(); i++) {
        for(int j = 0; j < results.size(); j++) {
        Point result = results.get(j);
            if(...) {
                //results.remove(j); or
                //results.remove(result);
            }
        }
    }
    

    As mentioned in the comments, this will not work for Set. In that case, you could simply keep a reference to the collection's iterator, and use that to remove the item:

    Iterator<Point> firstIter = results.iterator();
    while(firstIter.hasNext()) {
        Point p1 = iterator.next();
    
        Iterator<Point> secondIter = results.iterator();
        while(secondIter.hasNext()) {
            Point p2 = secondIter.next();
    
            if(...) {
                secondIter.remove();
            }
        }
    }