前文傳送門:Enumeration
上一篇,咱們談到了那個古老的迭代器Enumeration,還談到了取代他的新迭代器——Iterator。相比於以往,這個新物種又有哪些優勢呢?java
迭代器這個詞,在沒查找許多資料以前,我只知道個大概,我知道它能夠用來遍歷集合,可是至於它其中的奧妙,並無作深究。本篇文章關於Iterator迭代器作了小小的總結,鞏固學習,若是有理解錯誤,或敘述不當之處,還望你們評論區批評指針。編程
官方文檔對Iterator的解釋是:設計模式
不行不行,這描述也太簡略了,我繼續查找資料:ide
- 迭代器自己是個對象,建立迭代器的代價很小,一般被稱爲輕量級對象。
- 迭代器其實也是一種設計模式,它提供了一種方法順序訪問一個聚合對象中的各個元素,但又不暴露該對象的內部表示。
針對以上種種,我充滿了好奇,因而在複雜的繼承關係裏畫了又畫,最終才漸漸理清集合中所謂迭代器模式的體現,暫時以ArrayList爲例:
學習
hasNext():boolean
判斷下一個元素還有沒有,有就是true。next(): E
返回序列中的下一個元素。經過查看源碼,我發現,在這個Itr這個實現類中,定義了兩個指針:cursor
和lastRet
。(還有個屬性爲expectedModCount初始化爲ArrayList的版本號modCount,這部分與fail-fast機制相關,以後會再提)而cursor初始爲0,與專門用來和集合元素數目size作比較的。而lastRet初始化爲-1,若是成功執行next操做,將會加1變成0,也就是上面說的「下一個元素」可想而知,能夠把lastRet認爲是初始化爲第一個元素以前的指針,和將要返回的值的索引相同,這樣會好記一些。測試
除了上面兩個方法,JDK1.8新增了兩個方法,也是體現處它與老迭代器不一樣的新優點:支持了刪除操做。優化
remove():void
將新近返回的元素刪除。
須要注意的是:remove方法沒有新近返回的元素,也就是說lastRet<0,會拋出異常。若是移除成功,讓cursor往回退一格,lastRet重置爲-1。debug
forEachRemaining(Consumer<? super E> consumer):void
這個是JDK1.8中Iterator新增的默認方法:對剩餘的元素執行指定的操做。
可能不太好理解:咱們經過測試來講明一下:設計
List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); //建立一個Iterator對象 Iterator<Integer> it = list.iterator(); //返回第一個值 System.out.print(it.next()+" ");
測試結果很明顯,只輸出了第一個元素:1。
咱們繼續在原代碼的基礎上咱們的新方法:
it.forEachRemaining(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.print(integer+" "); } });
測試結果爲:1 2 3,在原來的基礎上,把剩下的元素都打印了出來。而這個新增的方法,其實和咱們熟悉的這個是同樣的:
while(it.hasNext()){ System.out.print(it.next()+" "); }
值得一提的是:咱們以前學習的加強for循環,在底層其實就是運用了Iterator,我經過IDE的debug調試功能,發如今調用運行到加強for循環時,自動調用了集合的iterator()方法,返回了一個Iterator的實現類實例。
經過對Iterator中定義方法的學習,咱們大概知道了迭代器的用途,就是從前向後一個一個遍歷元素,而無視其內部結構。欸,遍歷我都懂,可無視結構在哪裏體現啊?別急,下面來看一個例子,讓咱們無視兩個不一樣集合的結構:
首先咱們定義一個方法,它能夠接收一個迭代器對象:
public static void display(Iterator<?> T){ while(T.hasNext()){ System.out.print(T.next()); } }
而後咱們建立兩個不同的集合,一個是ArrayList,一個是HashSet,自己是無序的,咱們接下來應該會作相應的源碼學習。
//ArrayList 有序 List<String> list = new LinkedList<>(); list.add("天"); list.add("喬"); list.add("巴"); list.add("夏"); //HashSet 無序 Set<Integer> set = new HashSet<>(); set.add(11); set.add(22); set.add(33); set.add(44); display(list.iterator());//天 喬 巴 夏 System.out.println(); display(set.iterator());//33 22 11 44
能夠看出來,兩個不一樣集合的迭代器傳入display方法以後,都能用一種相同的方式訪問集合中的元素。
經過上面的一頓分析,咱們能夠肯定,迭代器這玩意兒,統一了訪問容器的方式。
最後,關於迭代器,還有一部份內容,在往後會作總結。 參考資料:《大話設計模式》、《Java編程思想》