1. 程式人生 > >java for-each的使用場景和使用方法

java for-each的使用場景和使用方法

   使用for-each的可以是一個數組,或者是實現Iterable<T>這個介面的物件(Collection<E>繼承了這個介面,所有集合類都可以使用for-each)

   既然for迴圈能遍歷一個數組或者集合,那麼為什麼還會有一個for-each做遍歷呢?下面(參考了jdk1.8api)舉例說明:

for迴圈遍歷每一個TimerTask型別的元素,然後呼叫其cancel方法。

void cancelAll(Collection<TimerTask> c) {
    for (Iterator<TimerTask> i = c.iterator(); i.hasNext();
) i.next().cancel(); }

  你能從上面的程式碼發現有什麼問題嗎?如上確實能實現遍歷操作集合元素的功能,但是迭代器變數在每個迴圈中出現三次,for-each構造擺脫了這樣的問題。

void cancelAll(Collection<TimerTask> c) {
    for (TimerTask t : c)
        t.cancel();
}

    冒號(:)讀作“in”,上面的迴圈讀作“對於c中的每個TimerTask t”。正如您所看到的,for-each構造
與泛型完美地結合在一起。它保留了所有型別的安全性。因為您不必宣告迭代器,所以不必為其提供通用宣告。
(編譯器會在背後為你做這件事,但你不必關心它。)
對兩個集合進行巢狀迭代時犯的常見錯誤:
List suits = ...;
List ranks = ...;
List sortedDeck = new ArrayList();

// BROKEN - throws NoSuchElementException!
for (Iterator i = suits.iterator(); i.hasNext(); )
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(i.next(), j.next()));
 問題是“外部”集合(套裝)上被呼叫了太多次。它在外部和內部集合的內部迴圈中被呼叫,這是錯誤的。
為了解決這個問題,在外迴圈的範圍內新增一個變數來儲存這個套裝:


// Fixed, though a bit ugly
for (Iterator i = suits.iterator(); i.hasNext(); ) {
    Suit suit = (Suit) i.next();
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(suit, j.next()));
}
那麼所有這些與for-each構造有什麼關係呢?它是為巢狀迭代量身定製的!如下所示:

for (Suit suit : suits)
    for (Rank rank : ranks)
        sortedDeck.add(new Card(suit, rank));
for-each構造也適用於陣列,它隱藏了索引變數而不是迭代器。以下方法返回int陣列中值的總和:

>// Returns the sum of the elements of a>
int sum(int[] a) {
    int result = 0;
    for (int i : a)
        result += i;
    return result;
}
  總結:那麼你應該什麼時候使用for-each迴圈呢?任何時候都可以。它真的美化你的程式碼。但不是在任何地方使用它。例如,考慮expurgate方法。該程式需要訪問迭代器才能刪除當前元素。for-each迴圈隱藏了迭代器,所以你不能呼叫remove。因此,for-each迴圈不能用於遍歷時有刪除操作。同樣,它不適用於需要在遍歷列表或陣列時替換元素的迴圈。最後,它不能用於必須並行迭代多個集合的迴圈。