我有在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)

我知道这应该意味着我正在更改对象,而迭代取决于该对象,但是我无法终生弄清楚可能会发生在哪里。任何帮助,将不胜感激。

最佳答案

您的堆栈跟踪显示代码subList中的某处(直接或间接)传递给 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 源来了解有关列表修改检查的更多信息。

10-08 02:24