第46條:for-each循環(huán)優(yōu)先于傳統(tǒng)的for循環(huán)

看看這段代碼有啥問題:

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()));

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

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

// 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循環(huán)在你的類型上迭代,你的用戶會永遠感謝你辟癌。
總之寒屯,與傳統(tǒng)的for循環(huán)相比,在簡潔及防錯方面黍少,for-each循環(huán)有巨大的優(yōu)勢寡夹,而且沒有性能損耗。只要可以使用就應該用之厂置。不幸的是菩掏,有三種普遍情況無法使用for-each循環(huán):
1、過濾-如果需要在集合上遍歷且移去選定的元素昵济,就要使用顯式的迭代智绸,并調用它的remove方法。
2砸紊、轉換-如果需要在list或數組上遍歷且要替換部分或所有的元素值传于,則需要list的迭代器或數組的索引去設置這些值。
3醉顽、平行迭代-如果需要并行的遍歷多個集合沼溜,則需要顯式的控制迭代器或索引變量,以便所有的迭代器或索引能協(xié)同推進(如上面的有問題的card和dice例子所示)游添。

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末系草,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子唆涝,更是在濱河造成了極大的恐慌找都,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廊酣,死亡現場離奇詭異能耻,居然都是意外死亡,警方通過查閱死者的電腦和手機亡驰,發(fā)現死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門晓猛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡辱,你說我怎么就攤上這事戒职。” “怎么了透乾?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵洪燥,是天一觀的道長磕秤。 經常有香客問我,道長捧韵,這世上最難降的妖魔是什么市咆? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮再来,結果婚禮上床绪,老公的妹妹穿的比我還像新娘。我一直安慰自己其弊,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布膀斋。 她就那樣靜靜地躺著梭伐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仰担。 梳的紋絲不亂的頭發(fā)上糊识,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音摔蓝,去河邊找鬼赂苗。 笑死,一個胖子當著我的面吹牛贮尉,可吹牛的內容都是我干的拌滋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼猜谚,長吁一口氣:“原來是場噩夢啊……” “哼败砂!你這毒婦竟也來了?” 一聲冷哼從身側響起魏铅,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤昌犹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后览芳,有當地人在樹林里發(fā)現了一具尸體斜姥,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年沧竟,在試婚紗的時候發(fā)現自己被綠了铸敏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡屯仗,死狀恐怖搞坝,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情魁袜,我是刑警寧澤桩撮,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布敦第,位于F島的核電站,受9級特大地震影響店量,放射性物質發(fā)生泄漏芜果。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一融师、第九天 我趴在偏房一處隱蔽的房頂上張望右钾。 院中可真熱鬧,春花似錦旱爆、人聲如沸舀射。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脆烟。三九已至,卻和暖如春房待,著一層夾襖步出監(jiān)牢的瞬間邢羔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工桑孩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拜鹤,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓流椒,卻偏偏與公主長得像敏簿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宣虾,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容