1. public Iterator<E> iterator() {
  2. return new Itr();
  3. }

属性

  1. int cursor; // 下一个要返回的元素的下标
  2. int lastRet = -1; // 最后一个要返回元素的下标 没有元素返回 -1
  3. int expectedModCount = modCount; //期望的 modCount

Itr的hasNext() 方法

  1. public boolean hasNext() {
  2. return cursor != size;
  3. }

Itr的next()方法

  1. public E next() {
  2. checkForComodification();
  3. int i = cursor;
  4. if (i >= size)
  5. throw new NoSuchElementException();
  6. Object[] elementData = ArrayList.this.elementData;
  7. if (i >= elementData.length)
  8. throw new ConcurrentModificationException();
  9. cursor = i + 1;
  10. return (E) elementData[lastRet = i];
  11. }
  12. final void checkForComodification() {
  13. if (modCount != expectedModCount)
  14. throw new ConcurrentModificationException();
  15. }
  16. 在迭代的时候,会校验modCount是否等于expectedModCount
  17. 不等于就会抛出著名的ConcurrentModificationException异常。什么时候会抛出ConcurrentModificationException
  18. public static void main(String[] args) {
  19. ArrayList arrayList = new ArrayList();
  20. for (int i = 0; i < 10; i++) {
  21. arrayList.add(i);
  22. }
  23. remove(arrayList);
  24. System.out.println(arrayList);
  25. }
  26. public static void remove(ArrayList<Integer> list) {
  27. Iterator<Integer> iterator = list.iterator();
  28. while (iterator.hasNext()) {
  29. Integer number = iterator.next();
  30. if (number % 2 == 0) {
  31. // 抛出ConcurrentModificationException异常
  32. list.remove(number);
  33. }
  34. }
  35. }
  36. list.remove(number); 当这行代码执行后,modCount++, expectedModCount还是为原来的值,所以会发生ConcurrentModificationException异常

那怎么写才能不抛出ConcurrentModificationException?很简单,将list.remove(number);换成iterator.remove();即可。why?请看Itr的remove()源码…

  1. public void remove() {
  2. if (lastRet < 0)
  3. throw new IllegalStateException();
  4. checkForComodification();
  5. try {
  6. ArrayList.this.remove(lastRet);
  7. cursor = lastRet;
  8. lastRet = -1;
  9. expectedModCount = modCount; !!!!!!期望的修改值被重新赋值
  10. } catch (IndexOutOfBoundsException ex) {
  11. throw new ConcurrentModificationException();
  12. }
  13. }