迭代器(iterator)
迭代器(iterator)
如果我們想遍歷陣列,這很容易,因為可以用陣列的下標跟蹤所在的位置,然而在連結串列中,節點沒有這樣的下標,怎樣才能提供給連結串列使用者類似於陣列下標的東西呢?這就是迭代器(iterator
)的作用。
我們知道新增到連結串列中的資料(data),都會包裝成一個節點(node),節點之間通過引用儲存了先後關係(pre、next)。但是由於在獲取資料時(如getFirst),返回的直接是資料(data),資料本身沒有其之後資料的引用,因此無法遍歷。
但是node存在這樣的引用,如果我們直接把node返回給使用者,讓使用者自己從node獲取資料,不就可以實現遍歷了嗎?我們可以提供一個getFirstNode()方法,然後按照類似以下程式碼片段進行遍歷:
- Nodenode=linkedList.getFirstNode();
- while(node!=null){
- Objectdata=node.getData();
- //...操作資料
- node=node.getNext();//獲取下一個node
- }
上述這樣的方式,的確是可以遍歷連結串列中的所有元素,但是卻不是一個好的設計方式,因為我們把連結串列的基礎資料結構Node直接暴露給使用者了,普遍的做法就是利用迭代器(iterator)來實現連結串列的迭代功能。
我們以上一節編寫的SingleLinkList
為例進行講解,為其提供一個迭代所有元素的迭代器
關於迭代器,Java中已經相關的介面定義java.util.Iterator
- publicinterfaceIterator<E>{
- /**是否還有更多的元素可以迭代*/
- booleanhasNext();
- /**返回下一個元素*/
- Enext();
- /**將迭代器當前迭代的元素,從連結串列中移除*/
- voidremove();
- }
1、在SingleLinkList中定義一個內部類NodeIterator,實現Iterator介面
- privateclassNodeIterator<T>implementsIterator<T>{
- privateNodenode;
- publicNodeIterator(Nodecurrent){
- this.node=current;
- }
- @Override
- publicbooleanhasNext(){
- returnnode!=null;
- }
- @Override
- publicTnext(){
- Objectdata=node.getData();
- node=node.getNext();
- return(T)data;
- }
- @Override
- publicvoidremove(){
- Tt=(T)node.getData();
- SingleLinkList.this.remove(t);
- }
- }
2、修改SingleLinkList,新增一個返回迭代器的方法
關於返回迭代器方法的名稱,是任意的,不過最好還是符合某種規範,java.lang.Iterable
介面,定義了這樣一個放回迭代器的方法
- publicinterfaceIterable<T>{
- Iterator<T>iterator();
- }
其返回型別就是Iterator
,現在你可能知道我們讓NodeIterator
實現Iterator介面的原因了,因為這樣,我們就可以將自己寫的迭代器通過Java的標準介面返回
現在我們讓SingleLinkList實現.Iterable介面,實現這個方法
- publicclassSingleLinkList<T>implementsIterable<T>{
- ...
- @Override
- publicIterator<T>iterator(){//可以看到,我們構建的時候,是把連結串列的第一個元素當做構造引數傳遞給了NodeIterator
- returnnewNodeIterator<T>(firstNode);
- }
- ...
- }
現在所有的工作已經完成,剩下的就是測試了
- @Test
- publicvoidtestIterator(){
- SingleLinkList<Integer>linkList=newSingleLinkList<Integer>();
- for(inti=0;i<10;i++){
- linkList.addFirst(i);
- }
- System.out.println("連結串列中元素:");
- linkList.display();
- System.out.println("\n開始迭代:");
- Iterator<Integer>iterator=linkList.iterator();
- while(iterator.hasNext()){
- Integernext=iterator.next();
- System.out.println(next);
- }
- }
執行程式,輸出:
連結串列中元素:
9 8 7 6 5 4 3 2 1 0 開始迭代: 9 8 7 6 5 4 3 2 1 0 |
可以看到我們的迭代器已經正常工作
特別的,由於我們的迭代器實現了Java的標準介面,所以我們可以使用java的增強for迴圈來進行迭代,如果沒有實現這些介面,是無法使用增強for迴圈的
- @Test
- publicvoidtestIterator(){
- SingleLinkList<Integer>linkList=newSingleLinkList<Integer>();
- for(inti=0;i<10;i++){
- linkList.addFirst(i);
- }
- System.out.println("連結串列中元素:");
- linkList.display();
- System.out.println("\n開始迭代:");
- //使用增強for迴圈進行迭代
- for(Integerdata:linkList){
- System.out.println(data);
- }
- }