9 java iterator concurrentmodification
我正在阅读有关ConcurrentModificationException以及如何避免它的内容.找到一篇文章.该文章中的第一个列表的代码类似于以下内容,这显然会导致异常:
List<String> myList = new ArrayList<String>();
myList.add("January");
myList.add("February");
myList.add("March");
Iterator<String> it = myList.iterator();
while(it.hasNext())
{
String item = it.next();
if("February".equals(item))
{
myList.remove(item);
}
}
for (String item : myList)
{
System.out.println(item);
}
Run Code Online (Sandbox Code Playgroud)
然后它继续解释如何用各种建议解决问题.
当我试图重现它时,我没有得到例外!为什么我没有得到例外?
根据Java API文档,Iterator.hasNext不会抛出ConcurrentModificationException.
检查后"January","February"从列表中删除一个元素.调用it.hasNext()不会抛出ConcurrentModificationException但返回false.因此,您的代码干净利落地退出.但是从不检查最后一个String.如果添加"April"到列表中,则会按预期获得异常.
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String args[]) {
List<String> myList = new ArrayList<String>();
myList.add("January");
myList.add("February");
myList.add("March");
myList.add("April");
Iterator<String> it = myList.iterator();
while(it.hasNext())
{
String item = it.next();
System.out.println("Checking: " + item);
if("February".equals(item))
{
myList.remove(item);
}
}
for (String item : myList)
{
System.out.println(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
来自ArrayList源码(JDK 1.7):
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
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();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
Run Code Online (Sandbox Code Playgroud)
对列表的每次修改操作都会增加ArrayList该modCount字段(列表自创建以来已修改的次数)。
创建迭代器时,它将存储modCountinto的当前值expectedModCount。逻辑是:
modCount == expectedModCountremove()方法修改,modCount则增加,但expectedModCount也会增加,因此modCount == expectedModCount仍然成立modCount则会增加,因此modCount != expectedModCount,这会导致ConcurrentModificationException但是,正如您从源代码中看到的那样,检查不是在hasNext()方法中执行的,而是在next(). 该hasNext()方法也仅将当前索引与列表大小进行比较。当您从列表中删除倒数第二个元素 ( "February") 时,这会导致以下调用hasNext()简单地返回false并在抛出 CME 之前终止迭代。
但是,如果删除倒数第二个元素以外的任何元素,则会引发异常。
| 归档时间: |
|
| 查看次数: |
1390 次 |
| 最近记录: |