一、Iterator的好處--面向接口編程
參考Java里用Iterator遍歷一個(gè)ArrayList里的數(shù)據(jù)比直接用ArrayList里的方法訪問(wèn)整個(gè)List里的數(shù)據(jù)要好嗎
- 更廣泛的使用范圍。
Iterator迭代器針對(duì)Collection設(shè)計(jì),但get(int index)、remove(int index)等一類的方法并不是Collection接口的標(biāo)準(zhǔn),也就是說(shuō),對(duì)ArrayList,即List的實(shí)現(xiàn),你能使用這些方法,但對(duì)于Collection的其他實(shí)現(xiàn),如Set等,你可能就必須使用Iterator了。 - 更好的異常控制。
Iterator迭代器允許調(diào)用者在在迭代期間對(duì)迭代器所指向的Collection進(jìn)行remove等操作,而對(duì)于這種情況,一般的for(int i = 0; i < Collection.size(); i++)遍歷方式可能就會(huì)出現(xiàn)IndexOutOfBoundsException。 - 更佳的性能。
對(duì)于數(shù)組形式的Collection,例如問(wèn)題中的ArrayList,兩種遍歷方式可認(rèn)為性能幾乎一致;但對(duì)于鏈表形式的Collection,例如同樣是List實(shí)現(xiàn)的LinkedList,一般的for(int i = 0; i < Collection.size(); i++)遍歷方式可能是噩夢(mèng),因?yàn)樵趂or loop的內(nèi)部,執(zhí)行g(shù)et(int index)、remove(int index)等一類的方法時(shí)需要再次進(jìn)行部分遍歷。即Iterator會(huì)從一個(gè)節(jié)點(diǎn)直接通過(guò)next指針獲得下一個(gè)節(jié)點(diǎn),遍歷時(shí)間復(fù)雜度始終是O(n),而一般的for loop的時(shí)間復(fù)雜度在鏈表的情況下會(huì)上升至O(n^2),n很大時(shí),性能消耗非常恐怖。
另外補(bǔ)充兩點(diǎn):
- 對(duì)于for循環(huán),我們還有一種叫做所謂for each的寫法,C#中就是for each,Java中是for(Object o : Collection os),這種寫法不僅僅是個(gè)語(yǔ)法糖,使代碼更漂亮、更簡(jiǎn)潔,更重要的是,for each實(shí)際上就是使用的迭代器,因此,code時(shí)始終使用foreach代替一般的for loop就對(duì)了!
//以三種方式遍歷集合List
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println("----------方式1-----------");
//第一種方式,普通for循環(huán)
for(int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}
System.out.println("----------方式2-----------");
//第二種方式,使用迭代器
for(Iterator<String> iter = list.iterator(); iter.hasNext();)
{
System.out.println(iter.next());
}
System.out.println("----------方式3-----------");
//第三種方式,使用增強(qiáng)型的for循環(huán)
for(String str: list)
{
System.out.println(str);
}
For-Each循環(huán)是JDK5.0的新特性(其他新特性比如泛型、自動(dòng)裝箱等)。當(dāng)遍歷集合或數(shù)組時(shí),如果需要訪問(wèn)集合或數(shù)組的下標(biāo),那么最好使用舊式的方式來(lái)實(shí)現(xiàn)循環(huán)或遍歷,而不要使用For-Each循環(huán),因?yàn)樗鼇G失了下標(biāo)信息。
- code時(shí),遵循夠用原則,參數(shù)傳遞等盡量面向接口,而不是具體的實(shí)現(xiàn)類,這有利于代碼的兼容以及后續(xù)升級(jí)。例如方法:
function(ArrayList os);
如果在function中用不到os的ArrayList獨(dú)有的特性,List已經(jīng)夠用,則寫成下面的形式更好,這樣調(diào)用者就更輕松了,他可以提供ArrayList之外的數(shù)據(jù)類型,如LinkedList:
function(List os);
同理,再進(jìn)一步,甚至可以寫成如下形式:
function(Collection os);
二、例子
import java.util.*;
public class Muster {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
Iterator it = list.iterator();
while(it.hasNext()){
String str = (String) it.next();
System.out.println(str);
}
}
}
Java中的Iterator功能比較簡(jiǎn)單,并且只能單向移動(dòng):
(1) 使用方法iterator()要求容器返回一個(gè)Iterator。第一次調(diào)用Iterator的next()方法時(shí),它返回序列的第一個(gè)元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。
(2) 使用next()獲得序列中的下一個(gè)元素。
(3) 使用hasNext()檢查序列中是否還有元素。
(4) 使用remove()將迭代器新返回的元素刪除。