__del__Iterator
Iterator.remove()
使用ArrayList时,一种很容易犯的错是在forEach遍历List时,删除其中元素
List<String> strList=new ArrayList<String>();
strList.add("1");
strList.add("2");
strList.add("3");
strList.add("4");
strList.add("5");
for(String item:strList) {
System.out.println(item);
if("2".equals(item)) {
strList.remove(item);
}
}
这样的代码会报如下异常:java.util.ConcurrentModificationException,这也很容易理解,在便利一个List的同时去修改该List是很不合理的,程序可能会报各种异常,这种行为是非法的。在ArrayList的实现上,使用了一个机制去检查这种非法操作。
注意ArrayList的add方法
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
其中expectedModCount为期望被修改的计数,而modCount为实际修改的计数,当两者相同时表明该List被正确操作,否则表明该List被非法操作过,此时会报异常!chechForComodification方法源码如下:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
该方法很简单粗暴的检查expectedModCount和modCount,如过不一致则报异常!该方法在多个地方被调用以保证List被正确的操作。
方法remove(Object)源码如下:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
方法remove()源码如下:
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();
}
}
这个地方还有一点迷,关于modcount,expectedCount几个关键性的变量是如何保证快速失败的,先停于此。
点赞
评论留言