1.ArrayList中的迭代器 ArrayList实现了迭代器接口,返回一个Itr内部类对象
public Iterator<E> iterator() { return new Itr(); }2.Itr实现了Iterator接口,有个三个实例成员变量 首先理清楚foreach或获取Iterator跌代器对象,就用expectedModCount变量, 记录当前集合modCount变量的次数expectedModCount = modCount。 如果在遍历过程中,发现modCount != expectedModCount不相等, 说明用集合add或remove等方法,修改了当前集合元素,就报并发修改异常。
1.下一个要返回的元素位置
2.最后一个返回的索引位置,如果没有,返回-1
3.expectedModCount表示期望修改的次数,初始化外部类当前的修改次数modCount, 成员内部类可以直接访问外部类的实例变量,每次外部类modCount发生变化会增加, 迭代的时候,会比较expectedModCount和modCount是否相同,不相同会报异常。
4.checkForComodification()检查是否发生变化,没有发生变化。下面就更新cursor和lastRet以及expectedModCount的值相同,返回元素对象
5.调用ArrayList的remove方法之前,同时更新上面第4点的值,所以能正确删除。调用remove删除方法之前必须next,不然会报错
List<Integer> list = new ArrayList<Integer>(); list.add(22); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ //iterator.next(); iterator.remove();Exception in thread “main” java.lang.IllegalStateException
protected transient int modCount = 0; private class Itr implements Iterator<E> { int cursor; //1 int lastRet = -1; //2 int expectedModCount = modCount;//3 public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); //4 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]; } public void remove() { //5 if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }检查方法
final void checkForComodification() { //modCount变量修改次数和期望修改的次数不一样就报异常 if (modCount != expectedModCount) throw new ConcurrentModificationException(); }总结 迭代器的好处在容器里面更通用,提供了遍历和数据分离的模式,不互相影响。这个Iterator接口对象的作用是遍历,设计成内部类的好处,可以方便直接访问自己集合内部元素。使用起来只要list.iterator()使用接口的引用就可以。 好比飞机汽车火车上的空姐 只为当前的飞机里元素服务,别的飞机有别的空姐,反应出每个集合的迭代器只为当前的集合服务.