1 问题 :在list<String> 中清空所有的记录,只使用使用单循环,不使用removeAll()
2 可以写出五种方式,代码如下:
Java代码
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
-
- public class ListRemoveTest {
- public static void main(String[] args) {
- ListRemoveTest test = new ListRemoveTest();
-
- System.out.println("-1-使用jdk5.0以后的增强for循环去remove");
- List<String> list = test.buildList();
- try {
- for (String str : list) {
- list.remove(str);
- }
- } catch (Exception e) {
- // java.util.ConcurrentModificationException
- e.printStackTrace();
- }
-
- System.out.println("-2-使用Iterator的remove");
- list = test.buildList();
- try {
- Iterator<String> iterator = list.iterator();
- while (iterator.hasNext()) {
- iterator.next();
- iterator.remove();
- }
- } catch (Exception e) {
- // java.lang.IllegalStateException
- e.printStackTrace();
- }
-
- System.out.println("-3-iterator遍历+list的remove");
- try {
- list = test.buildList();
- for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
- String str = (String) iterator.next();
- list.remove(str);
- }
- } catch (Exception e) {
- // java.util.ConcurrentModificationException
- e.printStackTrace();
- }
-
- System.out.println("-4-使用list的remove(int)方法. [由后向前删除]");
- list = test.buildList();
- for (int i = list.size(); i > 0; i--) {
- list.remove(i - 1);
- }
-
- System.out.println("-5-使用list的remove(int)方法. [由前向后删除]");
- list = test.buildList();
- for (int i = 0; i < list.size(); i++) {
- list.remove(0);
- }
- }
-
- private List<String> buildList() {
- List<String> list = new ArrayList<String>();
- list.add("a");
- list.add("b");
- list.add("c");
- return list;
- }
- }
3运行结果如下:
Xml代码
- -1-使用jdk5.0以后的增强for循环去remove
- java.util.ConcurrentModificationException
- -2-使用Iterator的remove
- -3-iterator遍历+list的remove
- at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)
- at java.util.ArrayList$Itr.next(ArrayList.java:753)
- at com.jdk.ListRemoveTest.main(ListRemoveTest.java:14)
- java.util.ConcurrentModificationException
- at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)
- at java.util.ArrayList$Itr.next(ArrayList.java:753)
- at com.jdk.ListRemoveTest.main(ListRemoveTest.java:39)
- -4-使用list的remove(int)方法. [由后向前删除]
- -5-使用list的remove(int)方法. [由前向后删除]
2,4,5运行正常,1,3抛出
java.util.ConcurrentModificationException
4问题原因:
1,3都是因为list的长度改变,Iterator执行next()方法时,调用checkForComodification()时出错,1,3是同一个问题,这两个方法remove操作都是执行的是ArrayList中的remove方法,根本原因在于expectedModCount与modCount他们的不相等,由于执行了ArrayList中的remove(),modCount在每一次循环值会发生改变,而expectedModCount并没有发生,在执行checkForComodification()方法就会抛出异常。
2之所以正确运行是因为调用了Iterator的remove方法,4,5不会执行checkForComodification()操作,所以不会出现这种异常。
5结论 :在执行remove()不要将ArrayList 与Interator混合使用,单独使用Interator以及ArrayList的删除都是OK的
6参考的源码
Iterator的next()方法:
Java代码
- public E next() {
- checkForComodification();
- int i = cursor;
- if (i >= size)
- throw new NoSuchElementException();
- Object[] elementData = ArrayList.this.elementData;
- if (i >= elementData.length)
- throw new ConcurrentModificationException();
- cursor = i + 1;
- return (E) elementData[lastRet = i];
- }
-
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
Iterator的remove()方法:
Java代码
- public void remove() {
- if (lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
-
- try {
- ArrayList.this.remove(lastRet);
- cursor = lastRet;
- lastRet = -1;
- //当执行remove操作后,将改变的modCount值重新赋给expectedModCount
- expectedModCount = modCount;
- } catch (IndexOutOfBoundsException ex) {
- throw new ConcurrentModificationException();
- }
- }
ArrayList的remove()方法:
Java代码
- /**
- * Removes the first occurrence of the specified element from this list,
- * if it is present. If the list does not contain the element, it is
- * unchanged. More formally, removes the element with the lowest index
- * <tt>i</tt> such that
- * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
- * (if such an element exists). Returns <tt>true</tt> if this list
- * contained the specified element (or equivalently, if this list
- * changed as a result of the call).
- *
- * @param o element to be removed from this list, if present
- * @return <tt>true</tt> if this list contained the specified element
- */
- ublic 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 remove method that skips bounds checking and does not
- * return the value removed.
- */
- private void fastRemove(int index) {
- //此处modCount发生了改变,但expectedModCount仍然未发生变化,所以再执行下一次循环时执行
- //Interator的next()方法当然会报错
- modCount++;
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- }