第46條:for-each循環優先于傳統的for循環

看看這段代碼有啥問題:

enum Suit { CLUB, DIAMOND, HEART, SPADE }
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING }
...
Collection<Suit> suits = Arrays.asList(Suit.values());
Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<Card>();
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); )
       for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
              deck.add(new Card(i.next(), j.next()));

如果你沒有發現這個bug也不用沮喪,許多專家級的程序員也時不時的犯這種錯誤。問題出在調用了太多的外層集合(suits)迭代器上的next方法。本來它應該在外層循環里被調用,這樣每個suit調用一次,然而,現在它在內層循環中被調用,變成了每個card調用一次。在你運行完suits,循環會拋出NoSuchElementException.

如果你很不幸,外層集合的長度是內層循環的倍數-或許因為它們是相同的集合-循環會正常中止,但結果卻不是你想要的。例如,考慮下面有問題的代碼,它企圖打印所有可能的成對骰子數。

// Same bug, different symptom!
enum Face { ONE, TWO, THREE, FOUR, FIVE, SIX }
...
Collection<Face> faces = Arrays.asList(Face.values());
for (Iterator<Face> i = faces.iterator(); i.hasNext(); )
       for (Iterator<Face> j = faces.iterator(); j.hasNext(); )
              System.out.println(i.next() + " " + j.next());

怎么解決這種問題:
方法1.

for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
       Suit suit = i.next();
       for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
              deck.add(new Card(suit, j.next()));
}

方法2.

for (Suit suit : suits)
       for (Rank rank : ranks)
              deck.add(new Card(suit, rank));

for-each不僅可在集合和數組上迭代,而且還可在任何實現了Iterable接口的對象上迭代。接口Iterablel有一個簡單的方法,隨for-each一起加入平臺,接口如下:

public interface Iterable<E> {
       // Returns an iterator over the elements in this iterable
       Iterator<E> iterator();
}

實現這個接口并不困難。如果所寫的類型代表一組元素,即便不讓他實現Collection接口也應該讓它實現Iterable接口。這會讓你的用戶可以通過for-each循環在你的類型上迭代,你的用戶會永遠感謝你。
總之,與傳統的for循環相比,在簡潔及防錯方面,for-each循環有巨大的優勢,而且沒有性能損耗。只要可以使用就應該用之。不幸的是,有三種普遍情況無法使用for-each循環:
1、過濾-如果需要在集合上遍歷且移去選定的元素,就要使用顯式的迭代,并調用它的remove方法。
2、轉換-如果需要在list或數組上遍歷且要替換部分或所有的元素值,則需要list的迭代器或數組的索引去設置這些值。
3、平行迭代-如果需要并行的遍歷多個集合,則需要顯式的控制迭代器或索引變量,以便所有的迭代器或索引能協同推進(如上面的有問題的card和dice例子所示)。

http://www.cnblogs.com/aoguren/p/4771589.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容