由於Java中數據容器眾多,而對數據容器的操作在很多時候都具有極大的共性,於是Java采用了迭代器為各種容器提供公共的操作接口。
使用Java的迭代器iterator可以使得對容器的遍歷操作完全與其底層相隔離,可以到達極好的解耦效果。
public interface Iterable<T>
Iterator<T> iterator()
Returns an iterator over a set of elements of type T
Collection接口拓展了接口Iterable,根據以上的對Iterable接口的定義可以發現,其要求實現其的類都提供一個返回迭代器Iterator<T>對象的方法。
迭代器Iterator<T>接口的的定義為:
Interface Iterator<E>
boolean hasNext()
Returns true if the iteration has more elements.
E next()
Returns the next element in the iteration.
void remove()
Removes from the underlying collection the last element returned by the iterator (optional operation).
注意:
從以上的定義中可以發現,似乎Iterable()接口和Iterator()接口完全一致,沒有任何區別。結合剛剛學習的內部類,可以發現這又是一個支持程序多樣化的巧妙設計,充分的支持了多態和解耦。
1、由於所有的Collection類型的對象都被強制要求implements Iterable 接口,故任何Collection對象都要能返回一個能遍歷其的迭代器Iterator。如果直接 implement iterator接口, Collection會直接要求具有hasNext()等方法。但是這種方法不具備多態性,即設定好了該如何執行hasNext()等操作,而且程序會顯得十分的臃腫和復雜。但是如果采用實施Iterable()接口和返回Iterator對象的方式,則會全然的不同,只要能夠返回Iterator對象,完全可以自己的需要進行遍歷方式上的自由定義。(即針對同一個接口,在其實現類中提供多樣、不同的方法)。
Example:
public class TestIterable { TestIterable(){ ScanAppleStore appleTree= new ScanAppleStore(); print("Try normal iterator:"); for(String str:appleTree) { print(str); } print("Try reverse iterator:"); for(String str:appleTree.reverseIterator()) { print(str); } } } class ScanAppleStore implements Iterable<String> { ArrayList<String> appleStore = new ArrayList<String>(); ScanAppleStore() { Collections.addAll(appleStore,"Sweet","Sour","Bitter","litter Sweet","litter Sour","litter Bitter"); print(appleStore); } public Iterator<String> iterator() { return new Iterator<String>(){ private int i=0; public boolean hasNext() { if(i<appleStore.size()) { return true; } else { return false; } } public String next() { return appleStore.get(i++); } public void remove() { print("not defined!"); } }; } public Iterable<String> reverseIterator() { return new Iterable<String>() { public Iterator<String> iterator(){ return new Iterator<String>(){ private int i=appleStore.size()-1; public boolean hasNext() { if(i>-1) { return true; } else { return false; } } public String next() { return appleStore.get(i--); } public void remove() { print("not defined!"); } }; } }; } }
從以上的例子中可以發現,為了實現對ScanAppleStore類對象的遍歷,共定義了兩種迭代器供選擇:
1、public Iterator<String> iterator() :該迭代器被定義為ScanAppleStore implements Iterable接口的方法, 采用常規的順序遍歷方式,for(String str:appleTree) 時自動被轉型調用。
2、public Iterable<String> reverseIterator():該迭代器采用了匿名內部類的方式實現Iterable接口,並返回Iterable對象,采用逆序的遍歷方式,for(String str:appleTree.reverseIterator())時,通過調用appleTree.reverseIterator()方法返回Iterable對象。
!foreach語法的標准形式為:for(T element : Iterable<T> elements)
由於Iterable接口要求實現iterator()方法,iterator()方法要求返回Iterator對象,Iterator定義了hasNext(), next(), remove()三種必須被實現的方法。
故實現Iterable的稍顯拖沓和復雜:
Example:
public Iterable<String> reverseIterator()
{
return new Iterable<String>()
{
public Iterator<String> iterator(){
return new Iterator<String>(){
private int i=appleStore.size()-1;
public boolean hasNext()
{
if(i>-1)
{
return true;
}
else
{
return false;
}
}
public String next()
{
return appleStore.get(i--);
}
public void remove()
{
print("not defined!");
}
};
}
};
}
}
此處采用了匿名內部類的方式,結構十分的清晰,此處更是體現出了內部類對於實現接口,強化OOP Java編程能力的重要性。
注意Iterable<T>中強調使用范型,故在定義的時候一定要注意指明類型。
迭代器接口要求實現其的類必須提供三種方法:
hasNext()
:遍歷過程中,判定是否還有下一個元素。(從Collection對象的第一個元素開始)
next()
: 遍歷該元素。(即取出下一個元素)
remove(): 移除剛剛遍歷過的元素。
從定義可以發現,該三個方法經常是被搭配使用的。
Examle:
Iteraotr it= arrayList.Iterator();
while(it.hasNext())
{
print(it.next());
it.remove();
}
基本思路為:在遍歷下一個元素前,先判斷其是否存在。對於想刪除的元素,必須先遍歷其,故 remove()方法總是接在 next()方法之后。