本文介绍了为什么 iterator.remove 不抛出 ConcurrentModificationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

iterator.remove()list.remove() 有什么不同,使得迭代器不会抛出异常和 list.remove() 是否抛出一个?最后,两者都在修改集合大小.

What does iterator.remove() do differently from list.remove(), so that iterator does not throw an exception and list.remove() does throw one? In the end, both are modifying the collection size.

请忽略这里的多线程.我只是在谈论 for-each 循环和迭代器循环.据我所知,for-each 循环只在内部创建一个迭代器.

Please ignore multi-threading here. I am just talking about a for-each loop and an iterator loop. As far as I know, a for-each loop creates an iterator only internally.

我很困惑.

推荐答案

ConcurrentModificationException 不会被 Iterator.remove() 抛出,因为这是允许的 迭代时修改集合的方法.这就是 javadoc for Iterator 说:

ConcurrentModificationException is not thrown by Iterator.remove() because that is the permitted way to modify an collection while iterating. This is what the javadoc for Iterator says:

从底层集合中移除此迭代器返回的最后一个元素(可选操作).每次调用 next() 只能调用一次此方法.如果在迭代过程中以除调用此方法以外的任何方式修改了基础集合,则迭代器的行为是未指定的.

如果您以任何其他方式更改正在迭代的集合,那么您很可能会遇到异常,具体取决于迭代器的实现以及您正在迭代的集合(或其他).(一些集合类不会给你一个 ConcurrentModificationException:检查各自的 javadoc 以了解它们如何指定他们的迭代器的行为)

If you change the collection being iterated any other way, then you are liable to get an exception, depending on the implementation of iterator, and the collection (or whatever) that you are iterating. (Some collection classes won't give you a ConcurrentModificationException: check the respective javadocs to see how they specify the behavior of their iterators)

如果您在同一个集合上有两个迭代器,并且您通过其中一个进行删除,您也可能会遇到异常.

You are also liable to get an exception if you have two iterators on the same collection, and you remove via one of them.

iterator.remove 与 list.remove 有何不同,即迭代器不会抛出异常而 list.remove 会抛出异常?

原因#1.如果您有一个非并发集合从同一调用堆栈上的两个位置同时更新,则该行为将破坏迭代 的设计不变量.保证非并发集合的迭代只看到集合中的所有元素一次.(相比之下,对于并发集合,这些保证是放松的.)

Reason #1. If you had a non-concurrent collection being updated simultaneously from two places on the same call stack, the behavior would break the design invariant for the iteration. An iteration of a non-concurrent collection is guaranteed to see all of the elements in the collection exactly once. (By contrast, with concurrent collections these guarantees are relaxed.)

原因#2.非并发集合类型未实现为线程安全的.因此,如果不同线程使用集合和迭代器更新集合,则可能会出现竞争条件和内存异常.这不是强烈的理由,因为无论如何您都会遇到这些问题.但是,以两种不同的方式进行更新会使问题变得更糟.

Reason #2. Non-concurrent collection types are not implemented to be thread-safe. Therefore, you could have race conditions and memory anomalies if the collection and iterator are used to update the collection by different threads. This is not strong reason because you will have these problems anyway. However, having the updates happening in two different ways makes the problem worse.

我只是在谈论 for-each 循环和迭代器循环.据我所知,for-each 循环仅在内部创建迭代器.

没错.for-each 循环实际上只是使用迭代器的 while 循环的语法糖.

That is correct. A for-each loop is really just syntactic sugar for a while loop using an iterator.

另一方面,如果你使用这样的循环:

On the other hand, if you use a loop like this:

    for (int i = 0; i < list.size(); i++) {
        if (...) {
            list.remove(i);
        }
    }

你不会得到ConcurrentModificationException,但是你需要为你删除的元素调整索引变量,另一个线程的更新容易导致你跳过元素或更多地访问它们不止一次.

you won't get ConcurrentModificationException, but you will need to adjust the index variable for the elements that you delete, and updates by another thread are liable to cause you to skip elements or visit them more than once.

这篇关于为什么 iterator.remove 不抛出 ConcurrentModificationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 03:17
查看更多