[英]What is internal implementation of Iteration in java that allows remove() method to work?
由foreach循环迭代时,列表中的任何项目都无法删除。 但是,当我们通过迭代器对其进行迭代时,可以通过迭代器的remove()方法将其删除。
我了解故障快速和故障安全的概念,并且也知道Iterator是java为我们提供删除选项的方式。 但是我想知道java提供的Iterator的remove()方法的内部实现,这有助于完成此操作。
import java.util.*;
public class RemoveCollection {
public static void main(String[] args) {
List<String> ls = new ArrayList<String>();
ls.add("apple");
ls.add("orange");
ls.add("kiwi");
Iterator it = ls.iterator();
while(it.hasNext()) {
it.next();
//works fine and the item is removed from list
it.remove();
}
ls.add("apple");
ls.add("orange");
ls.add("kiwi");
while(it.hasNext()) {
it.next();
//throws concurrentmodification exception
ls.remove();
}
}
}
您可以通过简单地查看JDK随附的ArrayList的源代码来了解这一点:
ArrayList具有此字段(从AbstractList继承):
protected transient int modCount = 0;
每次对列表进行操作时,它都会递增。 例如, ArrayList.remove()
具有以下指令:
modCount++;
ArrayList的迭代器具有以下代码:
int expectedModCount = modCount;
public E next() {
checkForComodification();
[...]
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
因此,如您所见,在迭代时,它将检查列表的modCount是否未被修改。
其remove()
方法执行以下操作:
ArrayList.this.remove(lastRet);
[...];
expectedModCount = modCount;
因此,它将元素从列表中删除,然后更新其expectedModCount
,以便在调用checkForComodification()
时使用迭代器完成的下一个操作不会失败。
要理解的关键是方法iterator()
返回一个可以访问列表内部结构的对象。 不仅可以迭代其元素,还可以检查在使用迭代器完成的两次操作之间是否已修改该列表。
List<E>
扩展AbstractList<E>
。 这个抽象类包含方法iterator()
,该方法返回一个新的Iterator(第287行)。 您可以看到源代码 :
public Iterator<E> iterator() {
return new Itr();
}
下面的几行(第330行)是private class Itr implements Iterator<E>
,它private class Itr implements Iterator<E>
,它定义并实现了第368行的remove()
方法:
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.