今天有空把iterator解析了一遍,算是彻底了解了它的原理,我们首先看它的源代码:让我们看看AbstractList的创建一个内部类
private class Itr implements Iterator<E> {}
大家可以看出这是jdk1.5出来的新特性迭代器,不需要知道集合中某个值所在索引进行循环输出这个集合中所有的值,是不是很强大?
在这个类中迭代器进行了初始化:
public Iterator<E> iterator() {
return new Itr();}
Itr是iterator迭代器的实现类。
大家是不是很想知道迭代器的执行过程,例如像这样的代码
List<String> list = new ArrayList<String>();
list.add("12");
list.add("123");
list.add("124");
list.add("124");
Iterator<String> it = list.iterator();
try {
int i = 0;
while (it.hasNext()) {
System.out.println();
it.next();
if (i == 2) {
System.out.println("111");
list.remove(i);
}
System.out.println(i);
i++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
当删除list集合中的倒数第二个不会报错,而删除其他的元素都会报java.util.ConcurrentModificationException异常,今天跟踪到源代码贴地明白了。
首先给大家看几个方法。
public boolean hasNext() {
return cursor != size();
}
这个方法是判断是否要继续执行while循环其中有两个属性:cursor是执行next()方法后是指向下一个值的游标就是索引,初始值为0;size()方法那
我们看看源代码它到底是什么?
public int size() {
return size;
}
就是集合长度,这个方法就在你所迭代集合中的方法,本案例中时list集合中的方法。
在让我们看看next()的方法吧
public Object next() {
checkForComodification();
try {
Object next = get(cursor);
lastRet = cursor++;
return next;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
大家很好奇checkForComodification();是什么方法?我们看看
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
我们来看看有两个属性:expectedModCount表示期待的modCount值,用来判断在遍历过程中集合是否被修改过。AbstractList包含一个modCount变量
,它的初始值是0,当集合每被修改一次时(调用add,remove等方法),modCount加1。因此,modCount如果不变,表示集合内容未被修改。说白了
expectedModCount就是刚开始list的集合长度,是始终不变的,Itr初始化时用expectedModCount记录集合的modCount变量,此后在必要的地方它会检
测modCount的值!
这些看完后我们就好理解了为什么我们删除倒数第二个不会出错,而其他的会出错。
当我们执行执行删除的操作的时候,我们的游标刚好指向最后一个位置就是list.size()-1,而我们此时删除了一个对象,size长度就要减1,则size
的长度为:list.size()-1;此时执行hasNext()方法返回false跳出循环,不会执行next()方法就不会报这样的异常了。
纯属个人理解,有什么不正确的问题,请留言指正!
解析java iterator 原理
最新推荐文章于 2024-06-01 23:39:08 发布