茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1675477 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_00019.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

爪哇咖啡屋 : [轉貼]神奇的 foreach

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]神奇的 foreach

神奇的 foreach



public void go(int[] arr) {
    for(int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
}

事實上很多時候,從頭到尾走訪一個陣列(或Collection)中所有元素,是很常見的需求,上面的寫法並沒有錯,只不過索引資訊基本上是不需要的,硬要寫是很冗長的事。

在J2SE 5.0之後,引進了foreach新語法,上例你可以這麼改寫:
public void go(int[] arr) {
    for(int element : arr) {
        System.out.println(element);
    }
}

這個語法其實不僅限於陣列,還可以用在List、Set等。例如若是List實作物件,可以這麼寫:
public void go(List<String> list) {
    for(String element : list) {
        System.out.println(element);
    }
}


如果 是Set也是可以的,例如:
public void go(Set<String> set) {
    for(String element : set) {
        System.out.println(element);
    }
}

事實上,只要是Collection介面的實作物件,都可以用foreach語法:
public void go(Collection<String> collection) {
    for(String element : collection) {
        System.out.println(element);
    }
}

Java的foreach語法,其實是編譯器給的語法蜜糖。如果foreach要走訪的是陣列,事實上,編譯器會自動展開為以下的程式碼:
public void go(int ai[]) {
    int ai1[] = ai;
    int i = ai1.length;

    for(int j = 0; j < i; j++) {
        int k = ai1[j];
        System.out.println(k);
    }
}

若foreach運用在Collection的實作物件上,其實編譯器會展開為:
public void go(Collection collection) {
    String s;
    for(Iterator iterator = collection.iterator();
        iterator.hasNext(); System.out.println(s))
        s = (String)iterator.next();
}

無論是Collection、List或Set,展開後皆利用iterator()方法傳回Iterator物件,並利用Iterator來移動、傳回下一個物件,這是 Iterator 模式 的實現。


在J2SE 1.4之前,Collection介面上直接定義了iterator()方法必須實作,因此所有Collection實作物件,皆需實作iterator ()。在J2SE 5.0之後,引進了Iterable介面,在介面中定義了iterator()方法,該方法必須傳回Iterator物件,而Collection介面繼 承了Iterable介面,因此所有Collection實作物件,皆需實作iterator(),因此所有Collection實作物件,都可以搭配使用foreach語法。

然而並非只有Collection介面的實作物件,才可以搭配foreach語法,事實上,由於Iterable介面的引進,使得只要是實作Iterable介面的物件,皆可搭配foreach語法來使用。例如:
public void go(Iterable<String> iterable) {
    for(String element : iterable) {
        System.out.println(element);
    }
}

不管你是List、Set還是Collection,只要是Iterable的物件,都可以用這個go,或是直接用foreach語法,像是:
  • Some.java

import java.util.Iterator;

public class IterableString >implements Iterable<Character> {
private String original;

public IterableString(String original) {
this.original = original;
}

public Iterator<Character> iterator() {
return >new InnerIterator();
}

>private class InnerIterator implements Iterator<Character> {
>public boolean hasNext() {
>return index < original.length();
>public Character next() {
>Character c = original.charAt(index);
>return c;
>public void remove() {>}
>}
}


IterableString類別實作了Iterable介面,因此你可以像以下這麼搭配foreach:
  • Main.java
     for(Character c : str) {
System.out.println(c);
}
}
}

若你反組譯程式,會發現編譯器作了這些事:
Character c;
for(Iterator iterator = str.iterator(); iterator.hasNext();
  System.out.println(c))
    c = (Character)iterator.next();

在JDK7之後,有不少API都實作了Iterable,例如NIO2的Path物件等。

原文出處: 神奇的 foreach
前一個主題 | 下一個主題 | | | |

討論串




Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|