class Itr implements Iterator<E> {
int cursor; // 指针变量 默认是0 指针从0开始的最多到length-1
int lastRet = -1; // index of last element returned; -1 if no such //lastRet中文意思是修改
private int modCount;
//将修改次数 modCount赋值给 期待值
int expectedModCount = modCount;
// prevent creating a synthetic constructor
//
Itr() {}
//dang 当集合里面的元素删了一个时 size会变
//当删了size-2时,cour会重新赋值为
//判断 ,如果指针不等于 长度 就是返回true
public boolean hasNext() {
return cursor != size;
}
//如果size等于指针,那么接下来的修改索引
// lastRet 所对应的数组索引 越界
//比如说长度是10,那么索引就是9,倒数第二个是8,
// next遍历方法后 指针变量是cour的值是8,cour++;然后给底层数组的索引赋值成8
// 删除了索引8所代表的元素后,继续while判断方法 cusor==size 判断为false
//(remove 底层删除方法是直接删除索引为【lastSet】的元素)
/*
public E remove(int index) {
这个是list底层的删除方法
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);//这个方法里面有赋值:modCount++;
return oldValue;
}
*/
@SuppressWarnings("unchecked")
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();
//检查 指针变量代表的数字有没有意义,如果有的话,就往下面读取
//同时返回下面的一个数 比如说刚开始是 0 那么就返回1
cursor = i + 1;//next一次 指针下移一格
return (E) elementData[lastRet = i];
}
//
// 1,hashN
public void remove() {
//第一次next以后 lastRet会等于0 c
if (lastRet < 0)//说明 没有使用next方法
throw new IllegalStateException();
//如果修改次数不等于期望修改次数就报异常 并发修改异常
checkForComodification();
try {
//删除倒数第二个数字时 lastRet(修改) 等于 length-2,
ArrayList.this.remove(lastRet);
//删一个数 集合长度少1 则相当于 指针cursor=原来的i =lastRet
cursor = lastRet;
//
lastRet = -1;
//将修改值赋值给期待修改值
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
今天晚上有个朋友问我迭代器ierator的源码问题,他问我我是怎么看的这个源码。实际上我看源码有个套路:
1,第一件事是看其中的成员变量,通过英文名字再根据变量作用猜测大致含义,一般说来,底层源码的变量名很规范,方法名也是。
2,就是分析方法,记录某个具体方法的具体作用。
3,把源码复制到idea工具中,把方法体删除,只留下自己需要看的东西。
比如说这个迭代器itretor的报异常的原因;
1,分析成员变量
int cursor; // 指针变量 默认是0 指针从0开始的最多到length-1
int lastRet = -1; // index of last element returned; -1 if no such //lastRet中文意思是修改
private int modCount;//后面会发现这个是要修改的索引,相当于游标cursor没修改值之前的值;
分析方法 hasNext();next();checkForComodification();等方法 记住各自的作用,然后挨个去沥青思路。
这个源码是我从idea中截取出来的,因为时间原因,就只当着源码分析了为什么用集合里面的方法在迭代时删除倒数第二个位置也不会报错的原因。 归根到底就是因为删除以后,程序直接在进循环前判断
cursor != size;
这个条件为假,没有执行了后面的checkForComodification();方法了,所以不报异常。
至于为什么报异常则是因为用list集合里面的删除方法,删除后 modCount++了,而exmodCount不变。所以调用判断是否相等的哪个方法,会报异常。而直接用迭代器的删除方法,删除后存在 expectedModCount = modCount;的赋值过程 所以不报异常
!!