注意:我知道Iterator#remove()方法。
Iterator#remove()
在下面的代码示例中,我不明白为什么List.removeinmain方法会 throws ConcurrentModificationException,但 不是 inremove方法。
List.remove
main
ConcurrentModificationException
remove
public class RemoveListElementDemo { private static final List<Integer> integerList; static { integerList = new ArrayList<Integer>(); integerList.add(1); integerList.add(2); integerList.add(3); } public static void remove(Integer toRemove) { for(Integer integer : integerList) { if(integer.equals(toRemove)) { integerList.remove(integer); } } } public static void main(String... args) { remove(Integer.valueOf(2)); Integer toRemove = Integer.valueOf(3); for(Integer integer : integerList) { if(integer.equals(toRemove)) { integerList.remove(integer); } } } }
原因如下:正如 Javadoc 中所说:
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法之外的任何方式,迭代器将抛出 ConcurrentModificationException。
这个检查是在next()迭代器的方法中完成的(你可以从堆栈跟踪中看到)。next()但是只有在传递为 true 时我们才会到达该方法hasNext(),这就是 for each 调用的方法,以检查是否满足边界。在您的 remove 方法中,当hasNext()检查是否需要返回另一个元素时,它会看到它返回了两个元素,现在在删除一个元素后,列表只包含两个元素。所以一切都很顺利,我们完成了迭代。不会发生并发修改的检查,因为这是在next()从未调用的方法中完成的。
next()
hasNext()
接下来我们进入第二个循环。在我们删除第二个数字后,hasNext 方法将再次检查是否可以返回更多值。它已经返回了两个值,但列表现在只包含一个。但是这里的代码是:
public boolean hasNext() { return cursor != size(); }
1 != 2,所以我们继续这个next()方法,它现在意识到有人一直在弄乱列表并触发异常。
希望能解决你的问题。
List.remove()``ConcurrentModificationException当它从列表中删除倒数第二个元素时不会抛出。
List.remove()``ConcurrentModificationException