开发者

ConcurrentModificationException, clarification needed [duplicate]

开发者 https://www.devze.com 2023-04-01 15:09 出处:网络
This question already has answers here: Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
This question already has answers here: Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop (31 answers) Closed 7 years ago.

The following mockup code ends up in ConcurrentModificationException, that happens (as i understand it), due to the fact that i am iterating over a set, which i am modifying.

Set<String> data = new HashSet<String>();
data.add("a=1");
data.add("b=2");
data.add("c=3");
data.add("d=4");

for (String s : data) {
    data.remo开发者_如何学Pythonve(s);
}

But why is it exactly? Please help clarify


You're violating the iterator's contract. From the ConcurrentModificationException javadoc,

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 throw this exception.


The exception is being thrown simply because you are modifying the collection (by calling data.remove(s)) while iterating over it. Java Collections generally have the requirement that they cannot be modified while iterating over their values.

From the official documentation:

it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.


You have to use Iterator to remove element from a Set


It's because the compiler actually inserts an Iterator and then uses the traditional for loop to iterate over the elements. If you modify the Collection on which the iterator was founded this would lead to undetermined behavior. To prevent this, ConcurrentModificationException is thrown.

See also here:

Item 7. Do not modify the list during iteration. While for-each syntax does not provide direct access to the iterator used by the equivalent basic for loop, the list can be modified by directly calling other methods on the list. Doing so can lead to indeterminate program behavior. In particular, if the compiler-inserted call to iterator() returns a fail-fast iterator, a java.util.ConcurrentModificationException runtime exception may be thrown. But this is only done a best-effort basis, and cannot be relied upon except as a means of detecting a bug when the exception does get thrown.

or the section on the for each loop in the Language Specification.

0

精彩评论

暂无评论...
验证码 换一张
取 消