此源码分析JDK版本为1.7,只是简单分析,算是个人看源码的一点小总结,随意性比较强,专业的还需百度。
private class Itr implements Iterator<E>{}
简介
私有内部类
private class Itr implements Iterator<E> {}
属性
//下一个元素返回的索引
int cursor;
//遍历上个元素的索引 如果没有则返回-1
int lastRet = -1;
//当前修改次数(参考ArrayList的modCount属性)
int expectedModCount = modCount;
构造方法
无
方法
//判断是否还有下一个
public boolean hasNext() {
//通过判断下一个下标是否为数组大小即可得出结果
return cursor != size;
}
//检查当前Itr修改次数和ArrayList是否一致,不一致则抛异常(并发异常) ps:final是防止子类覆盖此方法(ListItr)
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
//获取下一个元素
public E next() {
//检查修改次数是否一致
checkForComodification();
//定义i为下个元素的下标
int i = cursor;
//下标判断
if (i >= size)
throw new NoSuchElementException();
//定义elementData为ArrayList的数组
Object[] elementData = ArrayList.this.elementData;
//再次下标判断,此次判断不一致则说明数组修改过,抛出异常(并发异常)
//可能出现的场景1.ArrayList的remove()方法中中elementData[--size] = null,size--之前进入了此方法
if (i >= elementData.length)
throw new ConcurrentModificationException();
//定义下个元素的下标
cursor = i + 1;
//将lastRet定义为下个元素的下标(返回的最后一个元素的下标),返回该下标对应的值
return (E) elementData[lastRet = i];
}
//移出当前元素
public void remove() {
//如果无当前遍历元素则抛出异常
if (lastRet < 0)
throw new IllegalStateException();
//检查修改次数是否一致
checkForComodification();
try {
//调用ArrayList的remove方法(如果在遍历外remove会导致Itr中的expectedModCount没有修改抛异常)
ArrayList.this.remove(lastRet);
//定义下一个元素的下标为当前下标
cursor = lastRet;
//定义上个遍历下标为-1
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
private class ListItr extends Itr implements ListIterator<E> {}
简介
继承Itr的顺序遍历,自己封装的逆序遍历
逆序遍历是从构造方法传参的下标开始往上遍历(默认的构造方法传参为0,无法逆序遍历)
可以说ListItr存在的意义就是逆序遍历、set()和add(),如果不使用逆序遍历完全可以使用Itr
private class ListItr extends Itr implements ListIterator<E> {}
属性
继承Itr
构造方法(参数一般为数组的长度)
ListItr(int index) {
super();
cursor = index;
}
方法
//是否拥有上一个元素
public boolean hasPrevious() {
return cursor != 0;
}
//下一个元素下标
public int nextIndex() {
return cursor;
}
//上一个元素下标
public int previousIndex() {
return cursor - 1;
}
//获取上一个元素
public E previous() {
//检查修改次数是否一致
checkForComodification();
//定义i为上个元素的下标
int i = cursor - 1;
//下标判断
if (i < 0)
throw new NoSuchElementException();
//定义elementData为ArrayList的数组
Object[] elementData = ArrayList.this.elementData;
//可能出现的场景1.ArrayList的remove()方法中中elementData[--size] = null,size--之前进入了此方法
if (i >= elementData.length)
throw new ConcurrentModificationException();
//定义上个元素的下标
cursor = i;
return (E) elementData[lastRet = i];
}
//为当前下标重新赋值
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
//检查修改次数是否一致
checkForComodification();
try {
//调用ArrayList的set方法(如果在遍历外set会导致Itr中的expectedModCount没有修改抛异常)
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//为当前下标后增加值
public void add(E e) {
//检查修改次数是否一致
checkForComodification();
try {
int i = cursor;
//调用ArrayList的add方法(如果在遍历外add会导致Itr中的expectedModCount没有修改抛异常)
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
总结
1.在Iterator遍历时,对list进行set操作并不会抛出异常,也就是说存在脏数据问题
2.ListItr在Itr的基础上增加了逆序遍历、set()和add()
3.在遍历时对ArrayList的add和remove操作应该使用Itr或者其子类完成,防止出现ConcurrentModificationException
网友评论