Iterator的remove方法实际上如何删除一个对象

时间:2013-04-13 21:56:04

标签: java loops collections iterator

我们都知道,在迭代它时从集合中删除对象的最安全的“且可能只是安全的”方法是首先检索Iterator,执行循环并在需要时删除;

Iterator iter=Collection.iterator();
while(iter.hasNext()){
    Object o=iter.next()
    if(o.equals(what i'm looking for)){
        iter.remove();
    }
}

我想了解的内容,遗憾的是没有找到深入的技术解释,是如何执行此删除的, 如果:

for(Object o:myCollection().getObjects()){
    if(o.equals(what i'm looking for)){
        myCollection.remove(o);
    }
}

会抛出ConcurrentModificationException,“技术术语”Iterator.remove()做什么?它会删除对象,打破循环并重新启动循环吗?

我在官方文件中看到:

  

“删除当前元素。如果是,则抛出IllegalStateException   尝试拨打之前没有呼叫的remove()   下一个()。“

部分“删除当前元素”,让我想到“常规”循环中发生的完全相同的情况=> (执行相等测试并在需要时删除),但为什么Iterator循环ConcurrentModification安全?

2 个答案:

答案 0 :(得分:20)

你在迭代它时不能修改列表的原因是因为迭代器必须知道要为hasNext()和next()返回什么。

如何完成这项工作是特定于实现的,但您可以查看ArrayList / AbstractList / LinkedList等的源代码。

另请注意,在某些情况下,您可以使用此类代码作为替代方法:

List<Foo> copyList = new ArrayList<>(origList);
for (Foo foo : copyList){
  if (condition){
    origList.remove(foo);
  }
}

但是这段代码的运行速度可能稍慢,因为必须复制集合(仅限浅层复制),并且必须搜索要删除的元素。

另请注意,如果您直接使用迭代器,建议使用for循环而不是while循环,因为这会限制变量的范围:

for (Iterator<Foo> iterator = myCollection.iterator(); iterator.hasNext();){
...
}

答案 1 :(得分:18)

Iterator如何删除元素取决于其实现,对于不同的集合可能会有所不同。肯定它不会破坏你所处的循环。我刚刚看了如何实现ArrayList迭代器,这里是代码:

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();

    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}

因此它检查并发修改,使用公共ArrayList remove 方法删除元素,并增加列表修改的计数器,以便在下一次迭代时不会抛出ConcurrentModificationException。