java - 不确定 ConcurrentModificationException 的原因

标签 java collections concurrency

这是我的代码,用于在 Locale l 中构建可能的城市之旅(这不是最佳选择,只是让我的 AI 搜索抢先一步)。

我得到了一个ConcurrentModificationException,据我所知,当不止一段代码访问一个变量/集合并试图修改它时,就会发生这种情况。导致这段代码变得不快乐:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

我在添加元素时对其进行了修改,但由于 Iterator 没有添加(仅删除)方法,因此我正在使用集合的方法。

所以,我的问题是:

  1. 是我添加的元素导致了问题吗?
  2. 如果是,我该如何正确添加它以便 modCount 正确并且我不会得到 ConcurrentModificationException

下面是完整的方法,在发生 ConcurrentModificationException 的行上有注释:

public void construct() {
    tour = new ArrayList();
    ArrayList<City> lcl = new ArrayList(l.getCitys());

    tour.add(lcl.remove(0));
    tour.add(lcl.remove(1));

    while (!this.tourComplete()) {
        System.out.println(tour.size());
        Iterator tourit = tour.iterator();
        City g1 = (City) tourit.next();
        City g2 = (City) tour.get(lcl.indexOf(g1)+1);

        int gapDist = l.distanceBetweenCitys(g1, g2);

        while (tourit.hasNext()) {
            City C = null;
            int best = Integer.MAX_VALUE;

            for (Iterator lclit = lcl.iterator(); lclit.hasNext(); ) {
                City c = (City) lclit.next();
                int avg = (l.distanceBetweenCitys(g1,c) + 
                           l.distanceBetweenCitys(g2, c))/2 ;

                if ( (avg<gapDist) && (avg<best) ) {
                    C = c;
                    best = avg;
                }
            }

            if (C != null) {
                assert(best == Integer.MAX_VALUE);
                City A = tour.get(0);
                City Z = tour.get(tour.size()-1);

                boolean begin = true;

                for (Iterator lclit = lcl.iterator();   lclit.hasNext(); ) {
                    City c = (City) lclit.next();
                    int dist = l.distanceBetweenCitys(A,c);

                    if ( dist<best ) {
                        begin = true;
                        C = c;
                        best = dist;
                    }
                }

                for (Iterator lclit = lcl.iterator();   lclit.hasNext(); ) {
                    City c = (City) lclit.next();
                    int dist = l.distanceBetweenCitys(Z,c);

                    if ( dist<best ) {
                        begin = false;
                        C = c;
                        best = dist;
                    }
                }

                if (begin) {
                    // one of these is causing the problem
                    tour.add(0,C);
                }
                else {
                    // one of these is causing the problem
                    tour.add(C);
                }
            }
            else {
                // one of these is causing the problem
                tour.add(tour.indexOf(g2),C);
            }

            g1 = (City) tourit.next(); // this is where it all goes wrong 
            g2 = (City) tour.get(lcl.indexOf(g1)+1);
            gapDist = l.distanceBetweenCitys(g1, g2);
        }
    }
}

最佳答案

您不能在使用迭代器时修改基础集合(除非通过迭代器本身)。

我没有通过你的算法(你似乎想在任意位置插入,这可能很棘手),但也许你可以执行以下操作之一:

  1. 在第二个集合中收集您想要添加的所有内容,并在完成后执行 addAll

  2. 改为迭代集合的副本。

  3. 使用 ListIterator ,除了 remove 之外,它还有一个 add 方法。

  4. 根本不使用迭代器,只是通过索引访问 ArrayList(你已经在其他地方这样做了)

此外,您可以通过指定迭代器的类型(与您对列表所做的相同)来消除大量类型转换。

关于java - 不确定 ConcurrentModificationException 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1946168/

相关文章:

java - 这个模式有什么问题吗?

java - 如何使用 Java 将 MongoDB 中的数据保存到字符串中?

java - 用于存储对象的并发集合

java - box2d 不同步

Java:每隔几秒创建一次文件

java - 使用 GPS 和 XMLVM 的 J2ME 应用程序

java - 如何使点击区域仅成为图像非矩形部分的一部分?

Java线程设计

java - Spring Security方法规则: returned value contains a Collection

java - 如何在电子表格 controlsfx 的 GridBase 的 setCellValue 方法中迭代 List<String> 中的值?