2016-09-14 52 views
3

我有我的Main方法中进入for循环的代码。我无法找到我的java.util.ConcurrentModificationException的原因

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) 

我知道这应该意味着我改变的对象,而迭代取决于它,但我不能为了我的生活找出可能发生的事情。任何帮助,将不胜感激。

+2

你正在改变'output',但不一定在这个for循环中。这也可以通过另一段代码中的另一个线程来完成,但对'output'对象的引用完全相同。 – Tom

+0

尝试将增强型for循环替换为传统方法,即在每次迭代中计算大小。如果您完全修改列表(删除任何元素或添加任何元素),则会遇到增强for循环中的问题。 –

+2

看起来您正在传递由'Collections.synchronizedCollection'包装的子列表。但是当您迭代它时,原始列表正在被修改。 – vsminkov

回答

1

您的堆栈跟踪显示代码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的信息来源了解关于列表修改检查的更多信息。