Iterator源碼剖析
(一)簡介
Iterabtor是從jdk1.2就存在的接口,稱爲外部迭代器。支持對容器中的元素進行遍歷和移除,還支持流式遍歷
外部迭代器的特點是:可拔插。其迭代行爲可以掛載到待比較對象的外部, 此外,外部迭代器往往用來支撐內部迭代器的實現。
注意區別於內部迭代器Iterable和枚舉器Enumeration
外部迭代器的設計背後體現着迭代器設計模式的思想
(二)源碼分析
該接口就只有四種方法
// 是否存在未遍歷元素
boolean hasNext();
// 返回下一個元素
E next();
// 移除一個元素
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 流式遍歷。遍歷每個元素,並對其執行相應的擇取操作
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while(hasNext()) {
action.accept(next());
}
}
Consumer爲一個函數式接口,擇取從這裏實現。Lambda表達式參考【Java 8 in Action】Lambda表達式
我們看一下外部迭代器是如何實現自己的作用的。
我們切到AbstractList抽象類。很容易發現存在Itr類實現了外部迭代器的接口
// 獲取類的迭代器
public Iterator<E> iterator() {
return new Itr();
}
// 修改的次數--集合的增刪改查;都能引起modCount數值加1的操作
protected transient int modCount = 0;
private class Itr implements Iterator<E> {
// 下一個元素的索引
int cursor = 0;
// 當前元素的索引,該索引的元素被刪除了,則置爲-1.
int lastRet = -1;
// 預期修改的次數
int expectedModCount = modCount;
// 判斷是否有下一個元素
public boolean hasNext() {
return cursor != size();
}
// 返回下一個元素
public E next() {
// 調用判斷方法
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
// 這個方法體現的是Fail-Fast機制。
// expectedModCount預期修改的次數,modCount就是實際修改的次數;
// 在迭代器中,首先定義了一個expectedModCount=modCount默認值是0;這樣通過上面的checkForComodification()方法就可以判斷list集合在迭代過程中是否被其他線程修改過,這裏的修改就是集合的增刪改查;因爲這些操作都能引起modCount數值加1的操作,這樣就使得迭代失敗了。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ArrayList繼承了AbstractList抽象類。知曉源碼之後,我們再使用迭代器的API,一切都是那麼自然。
public static void main(String[] args) {
ArrayList<String> name= new ArrayList<>();
name.add("zhangsan");
name.add("lisi");
name.add("wangwu");
name.add("zhaoliu");
Iterator<String> it=name.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
還有,checkForComodification方法,體現的是Fail-Fast機制(面試會問)。也說明了爲什麼外部迭代器遍歷的時候,如果對集合進行操作,會拋出ConcurrentModificationException異常了。