This is my code to construct a possible tour of citys in a Locale l (it’s not optimal it’s just to give my AI search a head start).
I’m getting a ConcurrentModificationException, which to my knowledge happens when more than one piece of code accesses an variable / collection and attempts to modify it. Causing this code to get unhappy:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
I modify it as I’m adding an element in, but as the Iterator does not have a method for adding (only removing) I’m using the collection’s method.
So, my questions are:
- Is my adding the element what’s causing the problem?
- If it is, how do I add it in correctly so that the
modCountis correct and I don’t get theConcurrentModificationException?
Full method below, with a comment on the line where the ConcurrentModificationException happens:
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);
}
}
}
You cannot modify the underlying collection while using the iterator (except through the iterator itself).
I have not gone through your algorithm (you seem to want to insert at arbitrary positions, which could be tricky), but maybe you can do one of the following:
collect everything you want to add in a second collections, and doing an
addAllafter you’re done.Iterate over a copy of the collection instead.
Use a ListIterator, which does have an
addmethod in addition toremove.Not use an iterator at all, and just access the ArrayList by index (which you already do in other places anyway)
Also, you can do away with a lot of typecasts, by specifying the type of the iterator (same as you did with the list).