由于jdk 1.5推出了快速便利 for each,我们在编码过程中便利都是for each , 格式如下
for(Object o : objList) { ... }
现在的场景是,需要删除objList中的某几个元素,自然而然,我们会习惯性的写下如下语句:
int i = 0; for(Object o : objList) { if(o == value) { objList.remove(i); } i++; }
这时你就会发现报 java.util.ConcurrentModificationException 异常,此异常是迭代器抛出的异常,官方说明是:
The Iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Iterator的工作机制:
Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错 误。List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。
List removeList = new ArrayList() for(Integer i : intList) { if(i == 13) { removeList.add(i); } } //最后 if(removeList.size()>0) { intList.removeAll(removeList); } 二.用for循环遍历,原始书写方式
for(int i = 0; i < intList.size(); i++) { if(intList.get(i) == 13) { intList.remove(i); //此时要注意,因为list会动态变化不像数组会占位,所以当前索引应该后退一位 i--; } } 三.用迭代器自带的remove方法,这也是官方推荐的方法
Iterator it = intList.iterator(); while(it.hasNext()) { if(it.next() == 13) { it.remove(); } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206983.html原文链接:https://javaforall.net
