順便貼一篇,歡迎討論~
重拾聚集(Collection)
大家先來看段代碼吧:
List list = new ArrayList();
list.add("exception");
for (Iterator iter = list.iterator(); iter.hasNext();) {
???? String element = (String) iter.next();
???? list.remove(element);
}
這段代碼運行時會拋出異常,呵呵,不知道大家發現問題沒?
?
這段代碼會拋出:java.util.ConcurrentModificationException。也就是所謂的“Fail Fast”。用了很久Java了,才發現這么一個異常,著實郁悶了一把......啥都不說了,拿起書來,重新來過。
?
為什么要Iterator?
下面是一個Collection的總體圖:
?
?
??? 上面代碼涉及了一個經典的涉及模式-Iterator模式。既然涉及了這個模式,就要問問為什么這里要用這個模式。查了一下書,有這么幾句描述Iterator的:迭代邏輯沒有改變,但是需要將一種聚集變換成另一種聚集。因為不同的聚集遍歷接口不同,所以需要修改客戶端代碼。這幾句話沒錯,而且我們用Iterator都有如文章開頭示例的標準方式,然而仔細想來卻還有點問題。
??? 假設Iterator是為了實現遍歷方便。可是,我們幾個常用的聚集(如:ArrayList,LinkedList,Set等)都已經間接實現了Collection接口。而大家應該注意到Collection接口中有個size()方法。這樣的結果是,對所有實現了Collection的聚集而言,我們都可以通過for (int i = 0; i < list.size(); i++)這樣的形式實現遍歷。而且,JDK1.5還可以通過foreach的形式大大簡化代碼量。所以,這樣想來Iterator為了實現遍歷的方便而引入,顯然不成立。
??? 接著找找。我們可以注意到,Set和List兩個大類中一個很大的區別是:List提供get方法,而Set沒有提供get方法。這樣的結果是Set類只能往集合中放,卻不能從集合中取(從一般的常識來說,這樣做還是合理的)。呵呵,所以這里我只能猜想Iterator是不是是為了訪問Set中元素而設計的了。
??? 僅僅猜想,不知道大家有沒有什么更好的想法?
?
討論:
???? 跟朋友討論了一下,for(int i = 0; i < list.size(); i++)對應遍歷LinkedList來說是致命的。對ArrayList是O(n),而LinkedList則是O(n^2),這樣的效率是不能讓人接受的。
????如上所說,那么foreach的引入應該是在編譯層次對兩種不同數據結構進行了不同處理。而且成為了Iterator的替代。
??? 不過這里又引出了另一個問題——
???????????Iterator模式如何用在其他地方?作為一種設計模式Iterator應該有更廣的使用價值吧~
?
?
Iterator的缺點
- ??? 聚集中的元素有些是有順序的,而有些是沒有順序可言的。使用過度Iterator會產生一種元素順序的誤解。
- ??? Iterator給出的元素沒有類型。這點很致命啊。而且也是JDK1.5一大優勢。
- ??? Iterator使得某些同步的類在使用了Iterator后,成為不同步(不能說不同步,只是Iterator無法并發)。如Vector。
??? 這里沒有貶低Iterator的意思,只是實在看不出他有啥好處......
?
集合
能力有限,感覺了解還是太少,也沒太多好說的,只是有些區別應該注意一下。
- 繼承List的幾個類中,只有Vector是同步的。當然也包括Vector的子類Stack。
- 如果需要對不同步的List,Set等可以考慮使用Collections類中的方法。