国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

JAVA迭代器學習--在JAVA中實現線性表的迭代器

2019-11-15 00:26:04
字體:
來源:轉載
供稿:網友
java迭代器學習--在JAVA中實現線性表的迭代器

1,迭代器是能夠對數據結構如集合(ADT的實現)進行遍歷的對象。在遍歷過程中,可以查看、修改、添加以及刪除元素,這是它與一般的采用循環來遍歷集合中的元素不同的地方。因為,通常用循環進行的遍歷操作一般是逐個輸出元素,而用迭代器不僅僅只是查看元素,還可以改變元素(若迭代器支持remove())。

2,在JAVA類庫中定義了兩個常用的迭代器接口:Iterator和ListIterator,它們為迭代器指定了方法。給某個具體的ADT實現(如,單鏈表)添加迭代器功能時有以下兩種方式:(以鏈表為例)

①將迭代器方法添加到ADT線性表的操作中

②將迭代器定義為一個與ADT線性表相互作用的單獨的類。

②又分兩種情況:將該類定義在ADT線性表之外和將該類作為線性表的內部類(具體地說,將該類定義在實現線性表ADT接口的類的內部)

3,ADT線性表的display操作(見博文:http://m.survivalescaperooms.com/hapjin/p/4549492.html)執行了一次迭代,但是它僅僅是顯示線性表,若還想在遍歷的同時對線性表進行其它的操作呢?顯然,我們不希望每次需要遍歷ADT中的元素時,就構建循環,而是應將線性表的遍歷封裝起來。--此處可參考設計模式之迭代器模式

4,Iterator接口中只定義了三個方法

hasNext() :當迭代到最后一個元素時,再調用hasNext()將會拋出NoSuchElementException異常

next() :返回當前被迭代過的元素,剛剛被迭代器指針跳躍過的元素

remove() :該方法根據實際的需要來實現該方法,如:客戶不需要remove操作時,可以在實現remove()方法時拋出UnsupportedOperationException

注意:在JAVA中,迭代器位置不是在某個元素上,而是在集合的第一個元素之前、兩個元素之間或最后一個元素之后。

5,如何給ADT線性表添加迭代器功能呢?正如在第2點中提到的,可以有三種方式來實現

?在自己的類中實現迭代器方法,該類是公共類,與實現ADT的類分開了。這種迭代器實例為獨立類迭代器

?將遍歷操作定義為ADT操作,如:ListInterface 接口擴展了 Iterator,那么線性表對象就同時具有迭代器方法和線性表方法了。

?在自己的類中實現迭代器方法,該類是內部類,定義在實現ADT的類的內部,該類作為實現ADT類的一個私有內部類。稱之為內部類迭代器。

6,按方式?中進行迭代器的實現:

定義SeparateIterator類,implements Iterator<T>接口,在SeparateIterator類中實現對線性表的迭代。那么,如何讓迭代器去遍歷線性表呢?這就需要將迭代器與線性表聯系起來。聯系的方式如下:在SeparateIterator類中定義ListInterface類型的引用,然后構造函數中用實現了線性表接口的類的對象來實例化ListInterface引用,這樣,就可以在SeparateIterator中完成具體的對線性表的遍歷了。用戶程序只需要一個生成迭代器對象的方法,用戶程序通過調用該方法,得到一個迭代器對象,通過該迭代器對象來調用 hasNext方法、next方法 來對線性表進行遍歷。按這種方式實現的迭代器,對于線性表而言,它可以有多個迭代器同時在遍歷它。

具體代碼如下:

import java.util.Iterator;import java.util.NoSuchElementException;public class SeparateIterator<T> implements Iterator<T>{    //迭代器迭代器的對象是誰?它就是實現ListInterface接口的類的對象    PRivate ListInterface<T> list;//用來將迭代器與線性表聯系起來    private int nextPosition;//指示當前正在遍歷的元素    //執行remove時需要先調用next    private boolean wasNextCalled;//用來標記next是否被調用了        /*     * 構造器方法,用來初始化迭代器     * 參數類型為ListInterface,這樣,任何實現了該接口的類的對象     * 都可以作為參數傳遞給構造器,這是JAVA中的多態的性質     */    public SeparateIterator(ListInterface<T> aList) {        list = aList;        nextPosition = 0;        wasNextCalled = false;    }        @Override    public boolean hasNext() {        return nextPosition < list.getLength();    }    @Override    public T next() {        if(hasNext()){            wasNextCalled = true;            nextPosition++;            return list.getEntry(nextPosition);//調用線性表的方法getEntry來進行實際的遍歷        }        else            throw new NoSuchElementException("Illegal call to next(); " + "iterator is after end of list");    }    @Override    public void remove() {        if(wasNextCalled){            list.remove(nextPosition);            nextPosition--;            wasNextCalled = false;        }        else            throw new IllegalStateException("Illegal call to remove(); " + "next() was not called.");    }}

方式?和方式?中對迭代器的實現基本上相同。方式?就是:ListInterface 接口擴展了 Iterator,這樣具體實現ListInterface接口的類除了需要實現基本的線性表的方法(如,getEntry、add、clear、replace&hellip;…)還需要實現Iterator中定義的三個方法。

這樣當 new 一個實現了ListInterface接口的類的對象時,該對象就具有兩種性質:第一種性質是線性表,第二種性質是迭代器。說白了,即實現了ListInterface接口的類的對象它既是線性表又是迭代器。因為它即可以調用線性表的各種方法,又可以調用hasNext方法、next方法進行迭代。

對方式?而言,它是在實現ListInterface接口的類的內部定義一個實現Iterator接口的類(如,實現ListInterface接口的類為LList,則是在LList類的內部定義一個類,這個類 implements Iterator<T>)

這樣做的好處是什么呢?內部類可以直接訪問其外部類中的數據,因此,以內部類的方式實現迭代器就天然地將需要迭代的對象(線性表)與迭代器聯系起來了。相比于方式?而言,方式?更高效,因為方式?是直接遍歷線性表,而方式?是通過調用線性表的方法來遍歷線性表。

方式?的具體實現代碼如下:由于迭代器由內部類實現,因此這里貼出了整個類(包括外部類)的代碼:

  1 package linklist;  2   3 import java.util.Iterator;  4 import java.util.NoSuchElementException;  5   6 public class LList<T> implements ListInterface<T>{  7   8     private Node firstNode;//指向第一個結點的指針,該鏈表是不帶頭結點的單鏈表  9     private int length;//表示單鏈表的長度 10      11     //Node類中不需要定義訪問屬性的get方法以及set方法,因為Node是內部類,內部類的屬性可以直接在外部類中被訪問 12     class Node{ 13         //Node是內部類,其外部類中已經定義了T,故可以在這里使用通配符T 14         private T data;//結點的數據部分 15         private Node next;//結點的指針部分,指向下一個結點 16         //Node類中不需要默認構造器 17         public Node(T dataPortion){ 18             data = dataPortion; 19         } 20         public Node(T dataPortion, Node nextNode){ 21             data = dataPortion; 22             next = nextNode; 23         } 24     } 25      26     /* 27      * 需要在外部類(LList.java)中添加getIterator方法,該方法用來獲得迭代器對象 28      * 這樣,外部類對象調用getIterator()得到迭代器對象,該迭代器對象調用next進行線性表的迭代 29      *  30      */ 31     public Iterator<T> getIterator(){ 32         return  new IteratorForLinkList(); 33     } 34      35     private class IteratorForLinkList implements Iterator<T>{ 36         private Node nextNode;//標記當前正在遍歷的元素 37         private IteratorForLinkList(){ 38             nextNode = firstNode;//在內部類中直接訪問外部類中的firstNode數據域 39         } 40         @Override 41         public boolean hasNext() { 42             return nextNode != null; 43         } 44         @Override 45         public T next() { 46             if(hasNext()){ 47                 Node returnNode = nextNode; 48                 nextNode = nextNode.next; 49                 return returnNode.data; 50             } 51             else//已經遍歷到線性表末尾或線性表為空 52                 throw new NoSuchElementException("Illegal call to next()" + "iterator is after end of list."); 53         } 54         @Override 55         public void remove() {//該迭代器不支持remove()方法 56             throw new UnsupportedOperationException("remove() is not supported by this iterator"); 57         } 58     } 59      60     public LList(){ 61         clear(); 62     } 63     //獲取鏈表中指定位置處的結點 64     private Node getNodeAt(int givenPosition){ 65         assert (!isEmpty() && ((1 <= givenPosition) && (givenPosition <= length))); 66         Node currentNode = firstNode; 67         for(int counter = 1; counter < givenPosition; counter++){ 68             currentNode = currentNode.next; 69         } 70         assert currentNode != null; 71         return currentNode; 72     } 73      74     @Override 75     public boolean add(T newEntry) { 76         // 將每個新結點插入到鏈表的末尾,通過getNodeAt()方法來獲得最后一個元素的地址 77         Node newNode = new Node(newEntry); 78         if(isEmpty()){//插入第一個結點 79             firstNode = newNode; 80         } 81         else{//在其它位置插入結點 82             Node lastNode = getNodeAt(length);//這里每插入一個元素都需要遍歷一次鏈表,代價較大 83             lastNode.next = newNode; 84         } 85         length++; 86         return true; 87     } 88  89     @Override 90     public boolean add(int givenPosition, T newEntry){//在指定位置處插入結點 91         boolean isSuccessful = true; 92         if(givenPosition >= 1 && givenPosition <= length + 1){ 93             Node newNode = new Node(newEntry); 94             if(isEmpty() || givenPosition == 1){//在第一個位置處插入結點 95                 newNode.next = firstNode; 96                 firstNode = newNode; 97             } 98             else{//在其它位置插入結點 99                 Node nodeBefore = getNodeAt(givenPosition - 1);100                 Node nodeAfter = nodeBefore.next;101                 nodeBefore.next = newNode;102                 newNode.next = nodeAfter;103             }104             length++;105         }106         else107             isSuccessful = false;108         return isSuccessful;109     }110 111     @Override112     public final void clear() {//clear()在構造器中被調用了,所以此外用final修飾符113         firstNode = null;114         length = 0;115     }116 117     @Override118     public T remove(int givenPosition) {//刪除指定位置處的結點119         T result = null;120         if((!isEmpty()) && ((givenPosition >= 1) && (givenPosition <= length))){121             if(givenPosition == 1){//刪除第一個位置處的結點122                 result = firstNode.data;123                 firstNode = firstNode.next;124             }125             else//刪除表中其它位置結點126             {127                 Node nodeBefore = getNodeAt(givenPosition - 1);128                 Node nodeToRemove = nodeBefore.next;129                 Node nodeAfter = nodeToRemove.next;130                 nodeBefore.next = nodeAfter;131                 result = nodeToRemove.data;132             }133             length--;134         }135         return result;136     }137 138     @Override139     public boolean replace(int givenPosition, T newEntry) {//替換指定位置處結點的值140         boolean isSuccessful = true;141         if((!isEmpty()) && ((givenPosition >= 1) && (givenPosition <= length))){142             Node desireNode = getNodeAt(givenPosition);143             desireNode.data = newEntry;144         }145         else146             isSuccessful = false;147         return isSuccessful;148     }149 150     @Override151     public T getEntry(int givenPosition) {//獲取指定位置的結點的值152         T result = null;153         if((!isEmpty()) && ((givenPosition >= 1) && (givenPosition <= length))){154             result = getNodeAt(givenPosition).data;155         }156         return result;157     }158 159     @Override160     public boolean contains(T anEntry) {//判斷鏈表中的結點是否包含某個值161         boolean found = false;162         Node currentNode = firstNode;163         while(!found && currentNode != null){164             if(currentNode.data.equals(anEntry)){165                 found = true;166                 break;167             }168             currentNode = currentNode.next;169         }170         return found;171     }172 173     @Override174     public int getLength() {//獲取鏈表的長度175         return length;176     }177 178     @Override179     public boolean isEmpty() {//判斷鏈表是否為空180         boolean result;181         if(length == 0){182             assert firstNode == null;183             result = true;184         }185         else{186             assert firstNode != null;187             result = false;188         }189         return result;190     }191 192     @Override193     public void display() {//遍歷鏈表,顯示鏈表中的每個結點的值194         Node currentNode = firstNode;195         while(currentNode != null){196             System.out.println(currentNode.data);197             currentNode = currentNode.next;198         }199     }200 }

可以將該LList.java 與 http://m.survivalescaperooms.com/hapjin/p/4549492.html 博客中的LList.java 比較。(注意新增的第26--58行代碼,內部類迭代器的具體實現代碼)

前者是帶有迭代器的線性表實現,后者是不帶迭代器的線性表實現。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鸡西市| 汉川市| 双流县| 梁平县| 万年县| 从化市| 成都市| 平果县| 安阳县| 安西县| 阳信县| 信丰县| 土默特左旗| 会理县| 新沂市| 大石桥市| 韩城市| 永和县| 博野县| 嘉峪关市| 罗江县| 新平| 沙洋县| 云安县| 杭锦后旗| 阿巴嘎旗| 会东县| 蒙城县| 岗巴县| 邮箱| 称多县| 拉孜县| 库车县| 兴隆县| 盐山县| 土默特右旗| 汉沽区| 德江县| 山丹县| 吴桥县| 张家口市|