迭代器Iterator

迭代器Iterator

迭代器是一個對象,它的工作是遍歷並選擇序列中的對象。客戶端程序員不關心序列底層的結構。此外,迭代器通常被稱爲“輕量級”對象:創建它的代價小。因此,經常可以見到對迭代器有些奇怪的限制。
Java 的Iterator 就是迭代器受限制的例子,它只能用來:
1)使用方法 iterator()要求容器返回一個 Iterator。第一次調用Iterator 的next()方法時,它返回序列的第一個元素。
 
2)使用next()獲得序列中的下一個元素。
 
3)使用hasNext()檢查序列中是否還有元素。
 
4)使用remove()將上一次返回的元素從迭代器中移除。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Cat {
    private int id;
 
    public int getId() {
       return id;
    }
 
    public void setId(int id) {
       this.id = id;
    }
 
    Cat(int i) {
       id = i;
    }
}
 
public class Cats {
    public static void main(String[] args) {
       List<Cat> cats = new ArrayList<Cat>();
       for (int i = 0; i < 7; i++)
           cats.add(new Cat(i));
       System.out.println("before remove:"+cats.size());
       Iterator e = cats.iterator();
       while (e.hasNext()) {
           //e.remove();//java.lang.IllegalStateException
           System.out.println("Cat id:" + ((Cat) e.next()).getId());
           e.remove();
       }
       System.out.println("after remove:"+cats.size());
    }
}
結果:
before remove:7
Cat id:0
Cat id:1
Cat id:2
Cat id:3
Cat id:4
Cat id:5
Cat id:6
after remove:0
這裏必須注意remove()方法的使用,在調用該方法之前必須先調用next()方法。
2.迭代器ListIterator
該迭代器只能用於各種List類的訪問。ListIterator可以雙向移動。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
public class ListIteration {
    public static void main(String[] args) {
       List<String> stringList = new ArrayList<String>(Arrays.asList("a", "b", "c",
              "d", "e"));
       ListIterator<String> it = stringList.listIterator();
       while (it.hasNext())
           System.out.print(it.next() + "," + it.nextIndex() + ","
                  + it.previousIndex() + ";");
       System.out.println();
       //回溯
       while(it.hasPrevious())
           System.out.print(it.previous()+" ");
       System.out.println();
       System.out.println(stringList);
       it=stringList.listIterator(2);
       while(it.hasNext()){
           it.next();
           it.set("z");
       }
       System.out.println(stringList);
    }
}
結果:
a,1,0;b,2,1;c,3,2;d,4,3;e,5,4;
e d c b a
[a, b, c, d, e]
[a, b, z, z, z]
①next()得到下一個元素;previous()得到前一個元素。
nextIndex()得到下一個元素的索引號;previousIndex()得到前一個元素的索引號。
③hasNext()判斷是否還有後繼元素;hasPrevious()判斷是否還有前驅元素。
④listIterator()得到該集合的迭代器;listIterator(n)得到一個子迭代器,從原集合中第n+1個元素起(注意考慮第一個元素索引號爲0)至集合末尾的所有元素組成一個子迭代器。
⑤set(“newElement”)將當前元素替換爲newElement。這個方法的調用類似remove()方法,需要先調用next()方法。
3.Iterable接口與Foreach
Iterable接口包含一個能夠產生Iterator的iterator()方法,並且Iterable接口被foreach用來在序列中移動。因此如果創建了任何實現Iterable接口的類,都可以將它用於foreach語句中。
import java.util.Iterator;
public class IterableClass implements Iterable<String> {
    protected String[] words = ("And that is how "
           + "we know the Earth to be banana-shaped.").split(" ");
 
    public Iterator<String> iterator() {
       return new Iterator<String>() {
           private int index = 0;
 
           public boolean hasNext() {
              return index < words.length;
           }
 
           public String next() {
              return words[index++];
           }
 
           public void remove() {}
       };
    }
   
    public static void main(String[] args){
       for(String s:new IterableClass())
           System.out.print(s+",");
    }
}
結果:
And,that,is,how,we,know,the,Earth,to,be,banana-shaped.,
這個例子中,IterableClass類實現了Iterable接口,該接口只有一個方法:
Iterator<T> iterator();
使用內部類實現這個Iterator接口,該接口有三個方法:
boolean hasNext();
E next();
void remove();
 
但是,如果嘗試把數組當作一個Iterable參數傳遞會導致失敗。這說明不存在任何從數組到Iterable的自動轉換。
import java.util.Arrays;
public class ArrayIsNotIterable {
    static<T> void test(Iterable<T> ib){
       for(T t:ib)
           System.out.print(t+" ");
    }
   
    public static void main(String[] args){
       test(Arrays.asList(1,2,3));
       String[] strs={"A","B","C"};
        //test(strs);ERROR
       test(Arrays.asList(strs));
    }
}
4.實現特定功能的Foreach
前面已經討論了,foreach語法是通過Iterable接口實現移動的,所以如果需要改變foreach語句的邏輯功能,其實質就是覆蓋底層Iterable中Iterator接口中三個方法的邏輯實現。下面,我們實現反向的Foreach“效果”。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
@SuppressWarnings("serial")
class ReversibleArrayList<T> extends ArrayList<T> {
    public ReversibleArrayList(Collection<T> c) {
       super(c);
    }
 
    public Iterable<T> reversed() {
       return new Iterable<T>() {
           public Iterator<T> iterator() {
              return new Iterator<T>() {
                  int current = size() - 1;
 
                  public boolean hasNext() {
                     return current > -1;
                  }
 
                  public T next() {
                     return get(current--);
                  }
 
                  public void remove() {
                  }
               };
           }
       };
    }
}
 
public class AdapterMethodIdiom {
    public static void main(String[] args) {
       ReversibleArrayList<String> ral = new ReversibleArrayList<String>(
              Arrays.asList("To be or not to be".split(" ")));
       for (String s : ral)
           System.out.print(s + " ");
       System.out.println();
       for (String s : ral.reversed())
           System.out.print(s + " ");
    }
}
結果:
To be or not to be
be to not or be To
在這個例子中,ReversibleArrayList類又實現了一個Iterable接口,名爲reversed(),將其底層Iterator接口中的三個方法的邏輯實現爲反向的遍歷,就達到了反向Foreach的效果。從這個示例中,我們還可以注意到:
ReversibleArrayList<String> ral = new ReversibleArrayList<String>;
for (String s : ral)
//此處的ral其實是Iterable接口的引用,因爲ReversibleArrayList類是實現Iterable接口的。
本文出自 “子 孑” 博客,請務必保留此出處[url]http://zhangjunhd.blog.51cto.com/113473/51077[/url]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章