ArrayList源码解读三之Iterator(迭代器)
在ArrayList的iterator()方法中就只有创建一个类Itr。
public Iterator<E> iterator() {
return new Itr();
}
我们查看一下Itr这个类,发现它是实现了 Iterator接口的。
private class Itr implements Iterator<E> {
int cursor;
int lastRet = -1;
int expectedModCount = modCount;
Itr() {}
}
我们了解方法之前先了解变量作用
- cursor:表示光标,其作用是确定此时光标在位置的
- lastRet:默认是无元素状态,其作用是确定位置有元素的。
( lastRet=-1表示此位置无元素,lastRet表示此位置有元素) - modCount:记录ArrayList的操作次数
- expectedModCount:记录Iterator的操作次数
清楚了解变量的作用,我们接下来了解方法
(一)checkForComodification函数
作用是判断ArrayList的操作次数与Iterator的操作次数是否相一致,不一致则抛出异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
(二)next函数
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();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
步骤:
- 进行判断操作次数是否一致。
- 判断光标是否大于ArrayList数组的元素数量。
- 将ArrayList进行赋值给新的Object数组。
- 判断光标是否大于ArrayList数组的大小。
- 对光标进行+1。
- 将lastRet赋值,并且返回。
(三)remove函数
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
步骤:
- 判断lastRet的位置是否有元素
- 进行判断操作次数是否一致。
- 对ArrayList的数组进行移除当前lastRet位置的元素。
- 对光标进行移动。
- 将lastRet此时位置设置无元素。
- 更新expectedModCount修改次数。
注意:在使用过next函数前提下才能使用remove()函数,不然会抛出IllegalStateException()异常。
(四)forEachRemaining函数
作用:与foreach类似,forEachRemaining遍历Iterator的所有元素
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
步骤:
- requireNonNull判断consumer对象是否为空指针。
- 获取ArrayList中的元素数量、获取光标位置、创建新的Oject数组。
- 光标超过ArrayList的数量或者数组长度会返回或者抛出异常。
- 光标不等于ArrayList的数量以及Iterator和ArrayList操作次数一致的情况下进行循环。
(consumer.accept里面是空函数,具体函数内容模块需要传进来的consumer实现) - 对光标,以及lastRet赋值
- 判断Iterator和ArrayList操作次数是否一致
以上就是ArrayList中Iterator的源码实现。