switch...case && if...else效率比較和優化

weixin_34208283發表於2016-07-18

       以前一直都是在程式設計中,用switch...case和if....else混合一起使用。但是我個人的習慣是如果可以,我都會盡量使用switch語句進行條件判斷。這隻能說是個人習慣吧,以前也一直沒有想很多,只是單純的覺得比起if語句,使用switch可以簡化我的輸入,而且後面我在審視自己的程式碼的時候也會覺得比較容易讀懂。

       最近小學期上課的時候,是一位公司的老師給我們上課,我觀察了一下他的程式碼習慣,他傾向比較多的條件判斷的時候,就使用switch,但是在小範圍的條件判斷中,他比較喜歡用if,我覺得這其中應該是有一定道理的,突然想起之前我在看《高效能javascript》的時候,作者也提出了這方面的優化。特此重新回顧了一下之前的書裡的內容,結合網上大牛們的解釋,做一次歸納總結吧。

使用if-else還是switch,最流行的方法是基於測試條件的數量來判斷:條件數量越大,越傾向於使用switch而不是if-else。這通常歸結於程式碼的易讀性。這個觀點認為,當條件較少時,if-else更易讀,當條件較多時,使用switch更加易讀。--《高效能javascript》

之後,我在維基百科也搜了一下switch_statement的有關資料,關於它的Compilation,維基百科作出瞭如下的解釋:

1754582-8fd3ebfabab25f6e.png
維基百科_switch_statement關於彙編的部分截圖

也就是說,在編譯器中,它會將一系列的語句編譯成分支表,然後在判斷時,無需像if-else語句一樣一個個進行邏輯判斷,而是通過在case裡的值,對值進行搜尋,從而達到對搜尋的優化。我也在知乎搜尋了一下,但是發現不知道是不是我開啟方式有問題,關於這方面的解釋比較少,或者說。。問題太簡單了。。。然後我找到了如下作者的回答(如果涉及侵權請聯絡我,我將立刻刪除,謝謝。)

1754582-3bd9c4e1a0cd13bf.png
知友的回答

switch通過編譯成一個分支表來達到優化的目的,我個人感覺是通過空間的代價來換取時間。說完了switch...case,現在我們再來對比一下if-else,沒有對比就沒有傷害。它和switch不同,if-else語句會對一個個條件按順序進行查詢,直到找到符合條件的"入口"。也因為這個特性,所以,當條件數量很大,它和switch的差距就慢慢顯現出來了。

事實證明,大多數情況下switch比if-else允許得要快,但只有當數量條件很大時,才快得明顯。當條件增加的時候,if-else效能負擔增加的程度比switch明顯得多。因此我們傾向於在條件數量比較少的情況下使用if-else,而在條件數量較大的時候使用switch,出於效能考慮,這是合理的。--《高效能javascript》

我個人的使用習慣是,當只有涉及到true||false的時候,我才會傾向於使用if-else語句,如果涉及到常數,或者數值的判斷,我一般傾向於使用switch,事實證明,這種做法也是對的,出於對程式碼的可讀性也好,出於效能考慮來說,我覺得我的使用習慣好像是正確的。

但是這本書中,有提及對if-else的優化:

最小化到達正確分之前所需要判斷的條件數量,最簡單的方式是將最可能的出現的條件放在首位........if-else語句應該總是按照最大概率到最小概率的順序排序,或者,最小化條件判斷的次數,使用巢狀的方式等。

但是我個人傾向於,程式碼的易讀性,如果一味地使用巢狀,其實只會影響程式碼的可讀性。

查詢表【補充方案】

其實有時候優化條件語句的最佳方案是避免使用if-else和我switch,當有大量的離散數值時,查詢表的優勢就會慢慢體現出來,查詢表這整個過程就變成了資料查詢或者物件成員的查詢了。

1754582-6e0a5d7d948ad6c5.png
維基百科關於查詢表的相關描述

當單個key和value之間存在有邏輯對映關係是,查詢表的優勢就會體現出來。一個查詢表可以看做是一個陣列或者一個物件,通過索引操作來取代邏輯運算,由於這樣子的對映關係,可以讓執行效率提高。

查詢表最主要的優點是,不用任何條件判斷語句,即使候選值增加,也不會有額外的效能開銷。switch語句比較適合每個key都需要有獨特對應一個或者一系列的動作的時候。

關於switch...case && if...else效率比較和優化就到這裡了,一切共勉。本文仍存在很多不足,希望各位加以指點~謝謝。

# 補充於 2018-05-09

拋開我們所說的記憶體也好,效率也好,如果讓我來總結這兩個判斷的一個異同點,我更傾向於用使用場景和你解釋,我們更傾向於用 if 去判斷連續的區間 用 switch 去判斷離散分佈的可能取值,也就是說:

if 比較適用的場景是 目標點 落在某一個區間 例如 90 < x <100 之類的

switch 比較適用的場景是 x = blue  .... x = red ..... 之類的處理場景


推薦閱讀:

紅黑聯盟關於這方面的帖子

維基百科中文版-查詢表

相關文章