iterator與iterable

用Iterator模式實現遍歷集合
Iterator模式是用於遍歷集合類的標準訪問方法。它能夠把訪問邏輯從不一樣類型的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。
例如,若是沒有使用Iterator,遍歷一個數組的方法是使用索引:
for(int i=0; i<array.size(); i++) { ... get(i) ... } 
而訪問一個鏈表(LinkedList)又必須使用while循環
while((e=e.next())!=null) { ... e.data() ... } 
以上兩種方法客戶端都必須事先知道集合的內部結構,訪問代碼和集合自己是緊耦合,沒法將訪問邏輯從集合類和客戶端代碼中分離出來,每一種集合對應一種遍歷方法,客戶端代碼沒法複用。
更恐怖的是,若是之後須要把ArrayList更換爲LinkedList,則原來的客戶端代碼必須所有重寫。

爲解決以上問題,Iterator模式老是用同一種邏輯來遍歷集合:
for(Iterator it = c.iterater(); it.hasNext(); ) { ... } 
奧祕在於客戶端自身不維護遍歷集合的"指針",全部的內部狀態(如當前元素位置,是否有下一個元素)都由Iterator來維護,而這個Iterator由集合類經過工廠方法生成,所以,它知道如何遍歷整個集合。
客戶端從不直接和集合類打交道,它老是控制Iterator,向它發送"向前","向後","取當前元素"的命令,就能夠間接遍歷整個集合
首先看看java.util.Iterator接口的定義:
public interface Iterator { boolean hasNext(); Object next(); void remove(); } 
依賴前兩個方法就能完成遍歷,典型的代碼以下:
for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 對o的操做... } 
在JDK1.5中,還對上面的代碼在語法上做了簡化(可是限於只讀,若是須要remove,仍是直接使用iterator):
// Type是具體的類型,如String。 for(Type t : c) { // 對t的操做... } 
每一種集合類返回的Iterator具體類型可能不一樣,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator,可是它們都實現了Iterator接口,所以,客戶端不關心究竟是哪一種Iterator,它只須要得到這個Iterator接口便可,這就是面向對象的威力。html

----------------------------------------------------------------java

在遍歷的過程當中出現java.util.ConcurrentModificationException的問題參http://www.blogjava.net/EvanLiu/archive/2008/08/31/224453.html數組

 

 

用Iterator模式實現遍歷集合
Iterator模式是用於遍歷集合類的標準訪問方法。它能夠把訪問邏輯從不一樣類型的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。
例如,若是沒有使用Iterator,遍歷一個數組的方法是使用索引:
for(int i=0; i<array.size(); i++) { ... get(i) ... } 
而訪問一個鏈表(LinkedList)又必須使用while循環
while((e=e.next())!=null) { ... e.data() ... } 
以上兩種方法客戶端都必須事先知道集合的內部結構,訪問代碼和集合自己是緊耦合,沒法將訪問邏輯從集合類和客戶端代碼中分離出來,每一種集合對應一種遍歷方法,客戶端代碼沒法複用。
更恐怖的是,若是之後須要把ArrayList更換爲LinkedList,則原來的客戶端代碼必須所有重寫。

爲解決以上問題,Iterator模式老是用同一種邏輯來遍歷集合:
for(Iterator it = c.iterater(); it.hasNext(); ) { ... } 
奧祕在於客戶端自身不維護遍歷集合的"指針",全部的內部狀態(如當前元素位置,是否有下一個元素)都由Iterator來維護,而這個Iterator由集合類經過工廠方法生成,所以,它知道如何遍歷整個集合。
客戶端從不直接和集合類打交道,它老是控制Iterator,向它發送"向前","向後","取當前元素"的命令,就能夠間接遍歷整個集合
首先看看java.util.Iterator接口的定義:
public interface Iterator { boolean hasNext(); Object next(); void remove(); } 
依賴前兩個方法就能完成遍歷,典型的代碼以下:
for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 對o的操做... } 
在JDK1.5中,還對上面的代碼在語法上做了簡化(可是限於只讀,若是須要remove,仍是直接使用iterator):
// Type是具體的類型,如String。 for(Type t : c) { // 對t的操做... } 
每 一種集合類返回的Iterator具體類型可能不一樣,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可 能返回TreeIterator,可是它們都實現了Iterator接口,所以,客戶端不關心究竟是哪一種Iterator,它只須要得到這個 Iterator接口便可,這就是面向對象的威力。函數

----------------------------------------------------------------post

在遍歷的過程當中出現java.util.ConcurrentModificationException的問題參http://www.blogjava.net/EvanLiu/archive/2008/08/31/224453.html測試

 

若是想用foreach遍歷自定義類的集合,自定義類一般須要實現implement iterable接口. 該接口定義了Iterator<T> iterator()方法. 有些時候這個iterator方法能夠供用類裏面的集合屬性.iterator()返回.this

 

 

public class Teacher implements Iterable{

private String name;
private int age;


public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Iterator iterator() {
return new Itr();
}


public static void main(String[] args) {
Teacher t = new Teacher();
t.setName("aaaaaaa");
t.setAge(23);
for (Object o : t) {
System.out.println(o.toString());
}
}


private class Itr implements Iterator{
private int cursor=0; // 屬性的索引
private Field[] fields = Teacher.class.getDeclaredFields(); // 屬性的數組

public boolean hasNext() {

return cursor!=(Teacher.class.getDeclaredFields().length);
}

public Object next() {
Object o=null;
try{
fields[cursor].setAccessible(true); // 讓內部類能夠訪問外部類的私有屬性的值
o = fields[cursor].getName()+" "+fields[cursor].get(Teacher.this);
cursor++;
}catch(Exception e){
System.out.println(e);
}

return o;
}

public void remove() {
// TODO Auto-generated method stub

}

}
}.net

 

 

 

 

 

import java.util.Iterator;指針

//測試類
public class Exec {
public static void main(String[] args) throws Exception {
// 建立學生集合類
Students students = new Students(10);htm

// 經過for each語句迭代循環學生集合類的每一個元素
for (Object obj : students) {
Student stu = (Student) obj;
System.out.println(stu.getSid() + ":" + stu.getName());
}
}
}

// 支持for each迭代循環的學生集合類
class Students implements Iterable {
// 存儲全部學生類的數組
private Student[] stus;

// 該構造函數能夠生成指定大小的學生類變量數組,並初始化該學生類變量數組
public Students(int size) {
stus = new Student[size];
for (int i = 0; i < size; i++) {
stus[i] = new Student(String.valueOf(i), "學生" + String.valueOf(i));
}
}

// 實現Iterable接口的重要方法,返回自定義的迭代類變量
public Iterator iterator() {
return new StudentIterator();
}

// 實現Iterator接口的私有內部類,外界沒法直接訪問
private class StudentIterator implements Iterator {
// 當前迭代元素的下標
private int index = 0;

// 判斷是否還有下一個元素,若是迭代到最後一個元素就返回false
public boolean hasNext() {
return index != stus.length;
}

// 返回當前元素數據,並遞增下標
public Object next() {
return stus[index++];
}

// 這裏不支持,拋出不支持操做異常
public void remove() {
throw new UnsupportedOperationException();
}
}
}

// 學生類
class Student {
// 學生學號
private String sid;

// 學生姓名
private String name;

// 默認構造函數
public Student() {
}

// 支持屬性值初始化的構造函數
public Student(String sid, String name) {
setSid(sid);
setName(name);
}

// 學生學號的讀取函數
public String getSid() {
return sid;
}

// 學生學號的設置函數
public void setSid(String sid) {
this.sid = sid;
}

// 學生姓名的讀取函數
public String getName() {
return name;
}

// 學生姓名的設置函數
public void setName(String name) {
this.name = name;
}

// 格式化字符信息輸出
public String toString() {
return this.sid + ":" + this.name;
}
}

 

 

 

爲何必定要去實現Iterable這個接口呢? 爲何不直接實現Iterator接口呢?

看一下JDK中的集合類,好比List一族或者Set一族, 
都是實現了Iterable接口,但並不直接實現Iterator接口。 
仔細想一下這麼作是有道理的。由於Iterator接口的核心方法next()或者hasNext() 
依賴於迭代器的當前迭代位置的。 若是Collection直接實現Iterator接口,勢必致使集合對象中包含當前迭代位置的數據(指針)。 當集合在不一樣方法間被傳遞時,因爲當前迭代位置不可預置,那麼next()方法的結果會變成不可預知。 除非再爲Iterator接口添加一個reset()方法,用來重置當前迭代位置。 但即時這樣,Collection也只能同時存在一個當前迭代位置。 而Iterable則否則,每次調用都會返回一個從頭開始計數的迭代器。 多個迭代器是互不干擾的

相關文章
相關標籤/搜索