需要帮助根据比较值修改列表(ConcurrentModification)

时间:2015-07-07 17:12:26

标签: java concurrentmodification

我试图在整个点和他们的距离安排中看到有什么可能性(不要告诉我没有,这是我失败的项目)。

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);
        }
    }
}

基本上,我试图检查两个点是否有整数距离,如果没有,则从集合中删除它,并为所有点(保留)执行此操作。

但是,我得到一个ConcurrentModificationException并且我不确定如何重构它以完成相同的任务而不会以另一种方式激发错误。

有没有办法解决这个问题,还是只是Java的限制?

编辑:虽然重复的建议链接提供了洞察力,但回答“关注单个循环”已经超出了不适用的范围。如果这个问题是重复的,那么使用迭代器的前提是答案。

4 个答案:

答案 0 :(得分:1)

你可以这样做:

Iterator<Point> iterator = results.iterator();
while (iterator.hasNext()) {
  Point p1 = iterator.next();
  boolean shouldBeRemoved = false;
  for(Point p2 : results) {
    if (p2 != p1 && (Math.sqrt(Math.pow(p1.getX() - p2.getX(), 2)
                             + Math.pow(p1.getY() - p2.getY(), 2))
                     % 1 > 0)) {
      shouldBeRemoved = true;
      break;
    }
  }
  if (shouldBeRemoved) {
    iterator.remove();
  }
}

不同之处在于显然p1被移除而不是p2,但因为我们在这里处理Set ...

  

设置

中删除它

......排序并不重要,对吗?

答案 1 :(得分:1)

某些Collection实现使用“ fail-fast ”迭代器。在迭代时从Collection直接删除项目(使用Collection#remove)将导致该异常。

增强的for循环使用集合的迭代器迭代集合。

您可以将增强型循环更改为常规循环:

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);
        }
    }
}

如评论中所述,这不适用于Set。在这种情况下,您可以简单地保留对集合的迭代器的引用,并使用它来删除该项:

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();
        }
    }
}

答案 2 :(得分:0)

这似乎正在发生,因为您正在尝试删除相同的Point结构。考虑第一点的情况。 p1和p2都是结果中的第一个点。 p1和p2之间的距离为零,因为它们指的是同一点。然后你试图删除实际上是p1本身的p2。请参阅链接http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html,了解有关为什么即使在一个线程尝试访问和修改某些结构时也能获得此异常的原因。

您可以修改上述代码,如下所示: -

boolean[] if_deleted = new boolean[results.size()];

for (int i = 0; i < results.size(); ++i) {
    if_deleted[i] = false;
}

for (int i = 0; i < results.size(); ++i){
    for(int j = i + 1; j < results.size(); ++j)
            Point p1 = (Point)results.get(i);
            Point p2 = (Point)results.get(j);
            if (!if_deleted[i] && !if_deleted[j]) { 
                if (Math.sqrt(
                    Math.pow(p1.getX() - p2.getX(), 2)
                            +
                            Math.pow(p1.getY() - p2.getY(), 2))
                    % 1 > 0){
                        if_deleted[j] = true;
                        results.remove(p2);
                }
            }    
    }
}

for (int i = 0; i < results.size(); ++i) {
    if (if_deleted[i]) {
        results.remove(i);
    }
}

答案 3 :(得分:0)

我重构了

    for (int p1 = 0;  p1 < results.size() ; p1++){
        for (int p2 = p1;  p2 < results.size() ; p2++){
                if (Math.sqrt(
                        Math.pow(results.get(p1).getX() - results.get(p2).getX(), 2)
                            +
                        Math.pow(results.get(p1).getY() - results.get(p2).getY(), 2))
                        % 1 > 0){
                            results.remove(p2);
                            p2--;
                }
        }
    }

但我不确定它是否像我预期的那样工作。