java for-each的使用場景和使用方法
阿新 • • 發佈:2019-01-10
使用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迴圈不能用於遍歷時有刪除操作。同樣,它不適用於需要在遍歷列表或陣列時替換元素的迴圈。最後,它不能用於必須並行迭代多個集合的迴圈。