2008年9月5日

[Java] if-else pk switch,誰快?

技術文章又來啦,當沒題材時,技術文章就是最好的工具人。

今天要介紹的是之前在公司 Code Review 探討過的一個問題,if-else 跟 switch 誰快?不囉唆,直接公佈答案:大部分情況 switch 快,但絕少部份 if 快

switch 判斷的方式類似 HashMap,採用 Binary Tree 的方式,當有 8 個 case 時,最少需要判斷3 次才能找到要執行的區段,因為 2^3=8。這可能因為 Compiler 不同有不同的最佳方式,我用的是 JDK 1.4,推論是這樣。

但 if 就是從頭開始判斷,如果第一個條件就 match 到,那速度就超快的,即使後續有 n 個 if-else 都無所謂了。

所以結論就是如果已經知道非常大部分都會落在某一個選項,採用 if 的方式,把最常發生的選項放在 if 的第一個,保證速度最快。但如果每一個選項都有一定的機率會被判斷到,採用 switch 會是比較保險的選擇。

驗證的程式如下,第一個是 switch。

 1:   public static void caseSwitch(int a) {
 2:    long s = System.currentTimeMillis();
 3:    for (int i = 0; i < 100000000; i++) {
 4:     switch (a) {
 5:      case 3 :
 6:       break;
 7:      case 5 :
 8:       break;
 9:      case 7 :
10:       break;
11:      case 2 :
12:       break;
13:      case 6 :
14:       break;
15:      case 4 :
16:       break;
17:      case 1 :
18:       break;
19:      default :
20:       break;
21:     }
22:    }
23:    long e = System.currentTimeMillis();
24:    System.out.println("Switch Cost: " + (e - s));
25:   }

第二個是 if。


 1:   public static void caseIf(int a) {
 2:    long s = System.currentTimeMillis();
 3:    for (int i = 0; i < 100000000; i++) {
 4:     if (a == 3) {
 5:     } else if (a == 5) {
 6:     } else if (a == 7) {
 7:     } else if (a == 2) {
 8:     } else if (a == 6) {
 9:     } else if (a == 4) {
10:     } else if (a == 1) {
11:     }
12:    }
13:    long e = System.currentTimeMillis();
14:    System.out.println("If Cost: " + (e - s));
15:   }

當傳入的數值落在 if 跟 switch 的最後一個選項時,if 比較慢。

caseSwitch(1); // --> Switch Cost: 328
caseIf(1); // --> If Cost: 532

當傳入的數值落在 if 跟 switch 的第一個選項時,if 變得比較快了。

caseSwitch(3); // --> Switch Cost: 422
caseIf(3); // --> If Cost: 297

實際比較起來,執行一億次差不到半秒鐘,雖然說各有優勢,但優勢實在太小了,等有寫到十億次、一兆次的程式再來考慮就好,平常跑個幾千次的就隨便用了啦,差別實在太小了。


PS:有人會說那換成 char 會不會有所不一樣, 有空的人可以去測測看,我測試的結論是一樣。

6 則留言:

  1. 以前的java老師說過switch是個可遇不可求的東西,絕大多數時候,都得用字串來做條件式判斷,能夠用數字的機會實在是少之又少

    回覆刪除
  2. 不知道能不能发表评论。。呵呵,试试先!

    回覆刪除
  3. 可以,继续。。
    兄弟,拜读了上面的文章,有一个小问题:
    我用的是JDK6.0 update12
    把你的程序(台湾的兄弟是不是称它为程式)小改一下:
    public class SwitchAndIf {
    public static void main(String args[]) {

    System.out.println(3);
    SwitchAndIf.caseIf(3);
    SwitchAndIf.caseSwitch(3);
    System.out.println("------------------------------------");
    System.out.println(5);
    SwitchAndIf.caseIf(5);
    SwitchAndIf.caseSwitch(5);
    System.out.println("------------------------------------");
    System.out.println(7);
    SwitchAndIf.caseIf(7);
    SwitchAndIf.caseSwitch(7);
    System.out.println("------------------------------------");
    System.out.println(2);
    SwitchAndIf.caseIf(2);
    SwitchAndIf.caseSwitch(2);
    System.out.println("------------------------------------");
    System.out.println(6);
    SwitchAndIf.caseIf(6);
    SwitchAndIf.caseSwitch(6);
    System.out.println("------------------------------------");
    System.out.println(4);
    SwitchAndIf.caseIf(4);
    SwitchAndIf.caseSwitch(4);
    System.out.println("------------------------------------");
    System.out.println(1);
    SwitchAndIf.caseIf(1);
    SwitchAndIf.caseSwitch(1);
    System.out.println("------------------------------------");
    System.out.println(8);
    SwitchAndIf.caseIf(8);
    SwitchAndIf.caseSwitch(8);
    }

    public static void caseSwitch(int a) {
    long s = System.currentTimeMillis();
    for (int i = 0; i < 1000000000; i++) {
    switch (a) {
    case 3:
    break;
    case 5:
    break;
    case 7:
    break;
    case 2:
    break;
    case 6:
    break;
    case 4:
    break;
    case 1:
    break;
    case 8:
    break;
    }
    }
    long e = System.currentTimeMillis();
    System.out.println("Switch Cost: " + (e - s));
    }

    public static void caseIf(int a) {
    long s = System.currentTimeMillis();
    for (int i = 0; i < 1000000000; i++) {
    if (a == 3) {
    } else if (a == 5) {
    } else if (a == 7) {
    } else if (a == 2) {
    } else if (a == 6) {
    } else if (a == 4) {
    } else if (a == 1) {
    } else if (a == 8) {
    }
    }
    long e = System.currentTimeMillis();
    System.out.println("If Cost: " + (e - s));
    }
    }
    分别把8个位置的数据都拿来测试一下,得到结果如下:
    3
    If Cost: 1485
    Switch Cost: 2546
    ------------------------------------
    5
    If Cost: 1969
    Switch Cost: 3422
    ------------------------------------
    7
    If Cost: 2438
    Switch Cost: 4375
    ------------------------------------
    2
    If Cost: 2921
    Switch Cost: 1985
    ------------------------------------
    6
    If Cost: 3406
    Switch Cost: 3969
    ------------------------------------
    4
    If Cost: 3906
    Switch Cost: 2922
    ------------------------------------
    1
    If Cost: 4391
    Switch Cost: 1484
    ------------------------------------
    8
    If Cost: 4484
    Switch Cost: 4969
    很奇怪的问题,如果switch是二叉树算法的话至少应该是单数位计算要快些吧?难道是JDK6.0完全没有用二叉树?
    我的邮箱:
    mail2guanmin@yahoo.com.cn
    盼赐教!

    回覆刪除
  4. 對於以下這段話感到好奇
    "
    switch 判斷的方式類似 HashMap,採用 Binary Tree 的方式,當有 8 個 case 時,最少需要判斷3 次才能找到要執行的區段,因為 2^3=8。這可能因為 Compiler 不同有不同的最佳方式,我用的是 JDK 1.4,推論是這樣。
    "
    請問你如何得知判斷3 次才能找到要執行的區段???
    沒記錯的話, switch case 是一個條件一個條件由上而下去比對的
    以binary tree結構實踐switch case的話, 反而會慢掉吧?!!?

    回覆刪除
  5. 我google了, 發現自己無知, 謝謝~~

    回覆刪除

Related Posts Plugin for WordPress, Blogger...