已经是第二次碰到这个题目了。如果你以前没有专门的看这一块的话,很有可能你给出的答案是不正确的。
题目要求:
给出如下的程序,问如何删除 BBB 对应的元素,请把代码补充完整。
给出的代码框架:
[CODE]
import java.util.*;
class ArrayListTest { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("AAA"); list.add("BBB"); list.add("CCC"); list.add("DDD"); System.out.println(list); Iterator<String> it = list.iterator(); while(it.hasNext()) { // 需要实现的代码 } System.out.println(list); } }
[CODE]
这块代码的意图很明显,通过 iterator的方式删除元素。
如果你给出的代码是这个样子:
String toDel = it.next();
if(toDel.equals("BBB")) { list.remove(toDel); }
那么恭喜你,答错了! 运行时会抛出异常:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.next(AbstractList.java:343) at ArrayListTest.main(ArrayListTest.java:63)
抛出异常java.util.ConcurrentModification,为什么?这和 Iterator的内部实现有关系。有兴趣的话可以查看 Iterator 的源代码实现。 这里廖雪峰的一篇文章: Java源码分析:深入探讨Iterator模式 供参考。
要怎么实现呢? 是这样的,再添加一条语句:
String toDel = it.next();
if(toDel.equals("BBB")) { it.remove(toDel); // 需要添加这个语句 list.remove(toDel); }
调用 Iterator自身的remove()方法的目的是一并删除当前元素,它会自动同步expectedModCount和modCount的值。所以 checkForComodification()方法就不会抛出ConcurrentModificationException 异常了。
查看源代码,Iterator 中 remove() 方法的实现如下:
public void remove() { ... AbstractList.this.remove(lastRet); ... // 在调用了集合的remove()方法之后重新设置了expectedModCount: expectedModCount = modCount; ... }
文章中也给出建议:
要确保遍历过程顺利完成,必须保证遍历过程中不更改集合的内容(Iterator的remove()方法除外),因此,确保遍历可靠的原则是只在一个线程中使用这个集合,或者在多线程中对遍历代码进行同步。
所以,根据题目要求,所要完成的完整代码为:
[CODE]
import java.util.*;
class ArrayListTest { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("AAA"); list.add("BBB"); list.add("CCC"); list.add("DDD"); System.out.println(list); Iterator<String> it = list.iterator(); while(it.hasNext()) { String toDel = it.next();
if(toDel.equals("BBB")) { it.remove(toDel); // 需要添加这个语句 list.remove(toDel); } } System.out.println(list); } }
|