这是我的代码,用于在 Locale l
中构建可能的城市之旅(这不是最佳选择,只是让我的 AI 搜索抢先一步)。
我得到了一个ConcurrentModificationException
,据我所知,当不止一段代码访问一个变量/集合并试图修改它时,就会发生这种情况。导致这段代码变得不快乐:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
我在添加元素时对其进行了修改,但由于 Iterator 没有添加(仅删除)方法,因此我正在使用集合的方法。
所以,我的问题是:
- 是我添加的元素导致了问题吗?
- 如果是,我该如何正确添加它以便
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);
}
}
}
最佳答案
您不能在使用迭代器时修改基础集合(除非通过迭代器本身)。
我没有通过你的算法(你似乎想在任意位置插入,这可能很棘手),但也许你可以执行以下操作之一:
在第二个集合中收集您想要添加的所有内容,并在完成后执行
addAll
。改为迭代集合的副本。
使用 ListIterator ,除了
remove
之外,它还有一个add
方法。根本不使用迭代器,只是通过索引访问 ArrayList(你已经在其他地方这样做了)
此外,您可以通过指定迭代器的类型(与您对列表所做的相同)来消除大量类型转换。
关于java - 不确定 ConcurrentModificationException 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1946168/