ConcurrentModificationException Within One Thread
I at first thought it odd that a ConcurrentModificationException could be thrown w/in the context of a single Thread. But, what do you know, it can! And I seem to be getting better at writing code that does!
As a part of a recent hack, I wanted to remove a certain element from a list. As I was iterating over the list, I tried to find an object that met a certain criteria and then remove it, as follows:
void removeStuff() {
List<Recipient> list = service.populateList();
for (Recipient r : list) {
if (r.getProperty().equals(searchProperty)) {
list.remove(r);
}
}
}
Unfortunately, this will throw the ConcurrentModificationException. From the said Exception's JavaDoc:
"Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception."
Perfect. That too-aptly describes my miserable attempts. So, it sounds like I just have to wait until iteration is complete to then attempt modification. So, a quick fix might look something like this:
void removeStuff() {
List<Recipient> list = service.populateList();
Recipient toRemove = null;
for (Recipient r : list) {
if (r.getProperty().equals(searchProperty)) {
toRemove = r;
}
}
list.remove(toRemove);
}
Interestingly, and it was true in this case, the JavaDoc also states: "ConcurrentModificationException should be used only to detect bugs."
Update
My friend, Steve, found a better way to do this inline w/o the exception that employs a manual iterator:
Beaner beaner = null;
Iterator iter = list.iterator();
while (iter.hasNext()){
beaner = (Beaner) iter.next();
if (beaner.getType() == 3){
iter.remove();
}
}