解决此问题的最简单方法是不将负索引传递给list.remove().
发生此第二个异常的原因是remove执行部分范围检查,该检查仅检查传递的索引是否太大.它不会检查它是否为负,因为在这种情况下,它依赖于支持数组的访问来引发异常.
因此,对于负索引,在引发ArrayIndexOutOfBoundsException之前,将ArrayList的modCount递增.结果,在捕获此异常后尝试继续遍历列表将抛出ConcurrentModificationException.
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index); // ArrayIndexOutOfBoundsException is thrown here
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
return oldValue;
}
请注意list.remove(1000)不会导致此问题,因为在ModCount递增之前将抛出IndexOutOfBoundsException.
当然,如果元素删除成功,则ConcurrentModificationException仍然可能失败,因为在迭代List时安全地从List删除元素的唯一方法是使用Iterator的remove()方法.
还有一件事-我不确定您是否打算调用public E remove(int index)或public boolean remove(Object o).前者(由编译器选择的)尝试删除指定索引处的元素,而后者(如果找到)则删除指定元素.
对于List< Integer> ;,即使您要按元素删除,将int传递给该方法也将尝试按索引删除.如果要按元素删除,则应传递引用类型-list.remove(Integer.valueOf(-1)).