I got this code Snippet which is working fine.
import java.util.ConcurrentModificationException;
import java.util.*;
ArrayList<Object> s = new ArrayList<>();
s.add(null);
s.add("test");
try {
System.out.println(s + "\n");
for (Object t : s) {
System.out.println(t);
if (t == null || t.toString().isEmpty()) {
s.remove(t);
System.out.println("ObjectRemoved = " + t + "\n");
}
}
System.out.println(s + "\n");
} catch (ConcurrentModificationException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}
But after changing
s.add(null);
s.add("test");
to
s.add("test");
s.add(null);
The code throws a ConcurrentModificationException
So my question is why can I remove null if it's the first object in the list but not if it's the second one?
The first thing to understand is that the code is invalid, as it structurally modifies the list while iterating over it and this is not permitted (NB: this is a slight simplification, as there are pemissible ways to modify a list, but this is not one of them).
The second thing to understand is that ConcurrentModificationException
works on a best-effort basis:
Fail-fast iterators throw
ConcurrentModificationException
on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
And so invalid code may or may not raise ConcurrentModificationException
-- it's really up to the Java runtime and could depend on the platform, version etc.
For example, when I try [test, null, null]
locally, I get no exception but also an invalid result, [test, null]
. This is a different behaviour to the two behaviours that you observed.
There are several ways to fix your code, the most common of which is probably to use Iterator.remove()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With