最近在网上看到一片文章,说switch和if-else相比,由于使用了Binary Tree算法,绝大部分情况下switch会快一点,除非是if-else的第一个条件就为true,还给出了个例子,后来我把例子改了一下,如下:
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));
}
}
但是发现运算结果是:
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出于下风,那篇帖子说的是JDK1.4,我用的是JDK1.6,为什么会出现这种现象呢?就算是二叉树算法,至少也应该是单数位会快一点吧?
难道是JDK1.6中的switch换算法了?
盼各位大虾指教!

解决方案 »

  1.   

    这个问题我也问过 大企鹅回答过的额switch可以进行跳转优化,java中对switch有两种处理方式,生成不同的jvm指令,一是tableswitch,一个是lookupswitch. 
    对于case的分支比较密集的情况,如 Java code
    public class Test {    public static void main(String[] args) {
            int i = 3;
            switch (i) {
                case 0:
                    System.out.println("0");
                    break;
                case 1:
                    System.out.println("1");
                    break;
                case 3:
                    System.out.println("3");
                    break;
                case 5:
                    System.out.println("5");
                    break;
                case 10:
                    System.out.println("10");
                    break;
                case 13:
                    System.out.println("13");
                    break;
                case 14:
                    System.out.println("14");
                    break;
            default:
            System.out.println("default");
                    break;
            }
        }
    }使用tableswitch,得到 Java code
    public static void main(java.lang.String[]);
      Code:
       0:    iconst_3
       1:    istore_1
       2:    iload_1
       3:    tableswitch{ //0 to 14
            0: 76;
            1: 87;
            2: 153;
            3: 98;
            4: 153;
            5: 109;
            6: 153;
            7: 153;
            8: 153;
            9: 153;
            10: 120;
            11: 153;
            12: 153;
            13: 131;
            14: 142;
            default: 153 }
       76:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       79:    ldc    #3; //String 0
       81:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       84:    goto    161
       87:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       90:    ldc    #5; //String 1
       92:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       95:    goto    161
       98:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       101:    ldc    #6; //String 3
       103:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       106:    goto    161
       109:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       112:    ldc    #7; //String 5
       114:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       117:    goto    161
       120:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       123:    ldc    #8; //String 10
       125:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       128:    goto    161
       131:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       134:    ldc    #9; //String 13
       136:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       139:    goto    161
       142:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       145:    ldc    #10; //String 14
       147:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       150:    goto    161
       153:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       156:    ldc    #11; //String default
       158:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       161:    return}从中可以看到tableswitch使用的跳转表。它这样查找,如果case值不在//0 to 14之间,直接执行default,如果在此范围之内,则取目标值-0这一项作为目标,比如switch(i),i为3,则跳转到3-0=3,使用数组中的第三项作为目标,也就是3: 98;直接去执行98行。 如果case中的值比较稀疏,则使用lookupswitch: Java code
    public class Test2 {    public static void main(String[] args) {
            int i = 3;
            switch (i) {
                case 3:
                    System.out.println("3");
                    break;
                case 20:
                    System.out.println("20");
                    break;
                case 50:
                    System.out.println("50");
                    break;
                case 100:
                    System.out.println("100");
                    break;
            }
        }
    }编译为 Java code
    public static void main(java.lang.String[]);
      Code:
       0:    iconst_3
       1:    istore_1
       2:    iload_1
       3:    lookupswitch{ //4
            3: 44;
            20: 55;
            50: 66;
            100: 77;
            default: 85 }
       44:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       47:    ldc    #3; //String 3
       49:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       52:    goto    85
       55:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       58:    ldc    #5; //String 20
       60:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       63:    goto    85
       66:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       69:    ldc    #6; //String 50
       71:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       74:    goto    85
       77:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       80:    ldc    #7; //String 100
       82:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       85:    return
    可以看到其中的 
    3: lookupswitch{ //4 
    3: 44; 
    20: 55; 
    50: 66; 
    100: 77; 
    default: 85 } 
    这个就要挨着查表确定跳转位置了。
      

  2.   

    那我刚才这个例子应该是比较密集的分支,采用tableswitch咯,如果是这样的话应该是效率更高啊,为什么多数情况下反而会比if-else慢呢?
      

  3.   

    说实话  我也没有深入研究过这个问题的根源
    只是在实际开发中  没有人会去用很多很多else if的
    都是用 switch case 的  后者比较清晰  给人感觉就是一个脑子很清楚的人写出来的东西
    至于效率的本质  就让大企鹅去操心吧
      

  4.   

    我觉得你8个没有可比性啊  如果你弄100个出来  我觉得switch就很明显啦
      

  5.   

    系统的效率高低,不可能取决于使用了if还是switch,
    事由整体结构决定的!除非是开发编译器,偏执在这种问题上没有任何意义。
      

  6.   

    系统的效率高低,不可能取决于使用了if还是switch, 
    事由整体结构决定的! 除非是开发编译器,偏执在这种问题上没有任何意义。
      

  7.   

    这样说,就是ifelse或switch都一样??