不确定ConcurrentModificationException的原因

Gwi*_*lym 2 java collections concurrency

这是我的代码,用于构建一个可能的城市之旅Locale l(这不是最佳的,只是为了让我的AI搜索起步).

我得到了一个ConcurrentModificationException,据我所知,当多个代码访问变量/集合并尝试修改它时.导致此代码变得不快乐:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}
Run Code Online (Sandbox Code Playgroud)

我修改它,因为我正在添加一个元素,但由于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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Thi*_*ilo 5

使用迭代器时不能修改底层集合(通过迭代器本身除外).

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

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

  2. 相反,迭代集合的副本.

  3. 使用ListIterator,它还有一个add方法remove.

  4. 根本不使用迭代器,只需通过索引访问ArrayList(无论如何你已经在其他地方使用过)

此外,您可以通过指定迭代器的类型(与您对列表执行的操作相同)来消除大量的类型转换.