1.定義
Iterator的定義為:對Collection進(jìn)行迭代的迭代器,Iterator取代了Java Collection Framework中的 Enumeration。Iterator與Enumeration主要有兩點不一樣:
1.迭代器允許在調(diào)用者從集合中刪除元素
2.迭代器的方法名有所改進(jìn)
以上是Java Api對Iterator的介紹,該接口主要定義了如下代碼的規(guī)則
public interface Iterator<E> {
//是否有下一個元素
boolean hasNext();
//獲取當(dāng)前元素
E next();
//刪除元素
void remove();
}
在使用Iterator時,我遇到如下兩個問題,
1.Iterator是什么,這便是上述介紹的內(nèi)容
2.為何使用Iterator,換句話說Iterator能做什么,下面將通過ArrayList中的Iterator的實現(xiàn)介紹Iterator的原理及應(yīng)用
2.原理及實現(xiàn)
在ArrayList中有兩個內(nèi)部類,都實現(xiàn)了Iterator接口,分別為Itr與ListItr,如下首先介紹Itr的源碼
private class Itr implements Iterator<E> {
//游標(biāo)記錄當(dāng)前索引的位置,是從0開始的
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;//記錄元素修改記錄,若在迭代List時,modCount發(fā)生變化將會拋出ConcurrentModificationException異常
//判斷游標(biāo)是否到達(dá)最后的位置,若沒有表示還有元素,若有則沒有元素了
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
//校驗是否被修改(其實這里存在多線程問題,所以說ArrayList不是線程安全的)
checkForComodification();
int i = cursor;//當(dāng)前游標(biāo)的位置
if (i >= size)//若游標(biāo)的位置比數(shù)組長度還大則
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;//游標(biāo)向后移動1
return (E) elementData[lastRet = i];//返回值并且賦值
}
public void remove() {
//lastRet初始值為-1,若需要調(diào)用remove方法,則bi
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//刪除lastRet索引處的元素
ArrayList.this.remove(lastRet);
//游標(biāo)前移,由于是刪除remove方法刪除的是lastRet位置的元素則游標(biāo)需要前移才能保證可以遍歷到所有的元素
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//檢查列表是否修改,若修改則拋出異常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
通過源碼可以發(fā)現(xiàn)迭代器的方式遍歷列表是不需要知道list的長度的,只需要判斷是否具有元素就可以進(jìn)行遍歷了,如下代碼所示
//1.獲取迭代器
Iterator<String> ite = arrayList.iterator();
//2.判斷是否遍歷結(jié)束
while (ite.hasNext()){
System.out.println(ite.next());
}
在ArryList詳解中我有提到使用Iterator可以實現(xiàn)在對List進(jìn)行遍歷是進(jìn)行刪除操作,具體代碼如下所示
Iterator<String> ite = arrayList.listIterator();
while (ite.hasNext()){
if(ite.next() == "a")
ite.remove();
}
System.out.println(arrayList);
這里需要思考一個問題,ite.remove()方法調(diào)用的實際上是ArrayList的remove(index)方法,也改變了數(shù)組的長度大小并且數(shù)組元素也發(fā)生了變化,那為什么使用這種方式可以得到正常的結(jié)果?
其實這需要從迭代器的remove的源碼進(jìn)行分析, 下面舉例分析,list中的初始值為[a,b,c,d],當(dāng)lastRet=0時,此時cursor=1,首先執(zhí)行A處的代碼,此時list變成[b,c,d],若要重新遍歷那就要把cursor變成上次刪除出的元素的索引,即執(zhí)行B處的代碼,這里便是迭代器循環(huán)刪除元素時可以得到正常的結(jié)果原因,利用游標(biāo)的方式在刪除元素后移動游標(biāo)達(dá)到可以遍歷到所有元素的目的
ArrayList.this.remove(lastRet);//A
cursor = lastRet;//B
lastRet = -1;//C
expectedModCount = modCount;//D
3.總結(jié)
本文主要針對Iterator一個基本的實現(xiàn)做了相關(guān)的介紹,后續(xù)還會根據(jù)深入的去理解其中的原理,如有問題希望指正。