我找不到java.util.ConcurrentModificationException的原因

时间:2016-09-14 19:23:04

标签: java concurrentmodification

我的代码在我的Main方法中进入for循环。

for (List<Point2D> points : output) {
    currentPath = pathDistance(points);
    if (shortest == 0){
        shortest = currentPath;
    } else if (currentPath < shortest) {
        best = points;
        shortest = currentPath;
    }
}

其中pathDistance定义为

public static Double pathDistance(List<Point2D> path){
    double distance = 0;
    int count = path.size()-1;

    for (int i = 0; i < count; i++) {
        distance = distance + path.get(i).distance(path.get(i+1));
    }

    distance = distance + path.get(0).distance(path.get(count));
    return distance;
}

但我一直收到错误

Exception in thread "main" java.util.ConcurrentModificationException
   at java.util.SubList.checkForComodification(Unknown Source)
   at java.util.SubList.size(Unknown Source)
   at java.util.Collections$SynchronizedCollection.size(Unknown Source)
   at TSMain.pathDistance(TSMain.java:76)
   at TSMain.main(TSMain.java:203)

我知道这应该意味着我正在改变一个对象,而迭代依赖于它,但我不能为我的生活找出可能发生的地方。任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:2)

您的堆栈跟踪显示代码子列表中的某个位置(直接或间接)传递给Collections.synchronizedCollection。喜欢这个

Set<List<Point2D>> output = Collections.singleton(
    Collections.synchronizedCollection(data.subList(start, end)));

但是它不会复制data列表。并且points subList仍然指向data列表中的范围。 原始列表会在发生momet path.size()调用时被修改。

您可以通过执行明确的列表复制轻松解决问题,然后再将其传递给pathDistance

for(List<Point2D> points : output){
    List<Point2D> pointsCopy = new ArrayList<>(points)
    currentPath = pathDistance(pointsCopy);
    // rest of code using pointsCopy
}

我还应该注意到,代码中的同步似乎存在问题。在同步集合中包装子列表是一个坏主意,因为原始列表可能会以不安全的方式进行修改,无需正确同步。

您可以通过查看AbstractList#modCount来源了解有关列表修改检查的更多信息。