以List接口的实现类ArrayList为例:
应用迭代器遍历如下,while代码块内部允许使用迭代器删除(普通迭代器不能add)集合元素,但是不能调用集合的删除方法
List<String> list = new ArrayList<>();
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();it.remove();
// !!!l list.remove(it);
System.out.println(str);
}
下面是ArrayList的关于Iterator的部分源码(JDK8)截图
当调用集合对象的iterator方法时,返回一个new Itr();(一个迭代器对象)
ArrayList的内部类Itr实现类Iterator接口
- cursor 表示调用next方法时要返回的元素索引,初始化为0
- lastRet 表示上一次返回的元素索引,因为一开始未遍历过所以初始化为-1
- expectedModCount 表示预计的modCount值
- modCount 表示集合对象被更新(插入或删除)的次数
- Itr() 构造方法
内部类的hasNext方法,size就是集合的大小
内部类的next方法,先不看checkForComodification方法,代码块其他内容就是在做返回索引对应元素值的工作
checkForComodification方法,在每次调用next方法遍历时判断:modCount与expectedModCount是否相等,如果不相等,就说明modCount在迭代器初始化后改变了(集合更新了),发生了线程不安全的问题,即抛出异常。
这里用到了乐观锁的思想,即每次尝试遍历前,先判断集合是否更新
下面给出modCount在集合更新时的操作:
ArrayList继承了AbstractList,集合实例化时modCount为0
更新时:
其他更新也都更新了modCount
而expectedModCount除了在迭代器实例化时赋过值,其他地方均没有改变