1. 程式人生 > >[java學習筆記]Iterator和Iterable介面

[java學習筆記]Iterator和Iterable介面

    Iterator和Iterable都是java的迭代器介面,二者既有區別又有聯絡,下面從介面定義,實現和方法呼叫三方面分析兩介面的關係和使用方法。

1.介面定義

1.1 Iterable

    Iterable包含在java.lang中,使用時不需要import,其定義如下

public interface Iterable<Item>{
    Iterator<Item> iterator();
}

    可以看出Iterable介面提供了iterator方法(注意大小寫,和Iterator介面不同),該方法返回的是一個Iterator介面。這裡需要說明的是方法是可以返回介面
的,但在實際呼叫該方法時,真正返回的是實現這一介面的某個類的例項(後面會有舉例說明)。


1.2 Iterator

    既然Iterable返回的是Iterator介面,那我們就來看看Iterator的定義。與Iterable不同的是,Iterator是包含在java.util.Iterator類中,因此使用時需要先import下

public interface Iterator<Item>{
   boolean hasnext();  #判斷集合體是否到頭
   Item next();        #返回下一項的值
   void remove();      #刪除某項,本文不予討論
}

    Iterator看著就比Iterable正常多了,三個方法都很好理解。


2.介面實現

    下面以stack為例,解釋如何在一個新的collection中實現這兩個介面。
import java.util.Iterator;
public class ArrayStack<Item> implements Iterable<Item>{
    private Item[] a = (Item[]) new Object[100];
    private int N = 0;
    public void push(Item item){}
    public Item pop(){}
    
    public Iterator<Item> iterator(){
        return new ArrayIterator();
    }
    private class ArrayIterator implements Iterator<Item>{
        private int i = 0;
        public boolean hasNext() {return i < N;}
        public Item next() {return a[i++];}
        public void remove() {}
    }
}

    需要注意的是,stack實現的是Iterable介面,並通過Iterable中的iterator方法(還是注意區分大小寫),返回一個ArrayIterator類的物件,而ArrayIterator正是實現了Iterator方法的一個類,這就是前面說的方法返回介面,實際上是返回了一個實現了該介面的類的例項。這裡可能會有人問,為什麼一定要先實現Iterable介面,而不直接實現Iterator介面呢,這樣多寫一個內部類不是很麻煩嗎? 
      其實理解起來也很容易,在網上看到一段解釋說的很明白:

     因為Iterator介面的核心方法next()或者hasNext() 是依賴於迭代器的當前迭代位置的。 如果Collection直接實現Iterator介面,勢必導致集合物件中包含當前迭代位置的資料(指標)。 當集合在不同方法間被傳遞時,由於當前迭代位置不可預置,那麼next()方法的結果會變成不可預知。 除非再為Iterator介面新增一個reset()方法,用來重置當前迭代位置。 但即使這樣,Collection也只能同時存在一個當前迭代位置。 而Iterable則不然,每次呼叫都會返回一個從頭開始計數的迭代器。 多個迭代器是互不干擾的。 

     出處:點選開啟連結


3.介面方法呼叫

    Iterator呼叫的例子在網上就太多了,為了文章概念的完整性,這裡僅列出最簡單的兩種呼叫。
ArrayStack<String> as = new ArrayStack<String>();
Iterator<String> i = as.iterator();
while(i.hasNext()){
    String s = i.next();
    StdOut.println(s);
}
上面是標準的呼叫Iterator進行遍歷輸出的例子,第二行程式碼可能會帶來一些誤解,看上去好像介面被例項化了,其實不然。我們知道介面是不能被例項化的,和上面方法返回介面類似,這裡的“介面例項化”的其實是一個實現了這個介面的類的物件,換句話講第二行等同於 
Iterator<String> i = new ArrayIterator();
     只不過ArrayIterator是一個內部的私有類,我們不能直接呼叫它,需要用iterator方法來完成這一過程。 
 

    除了上面的標準寫法,還有一種簡練的foreach語句,也就是某些人說的增強for語句:

for(String s: as){
    StdOut.println(s);
}

   p.s. 可以,這很python