zoukankan      html  css  js  c++  java
  • 为什么说在使用多条件判断时switch case语句比if语句效率高?

      在学习JavaScript中的if控制语句和switch控制语句的时候,提到了使用多条件判断时switch case语句比if语句效率高,但是身为小白的我并没有在代码中看出有什么不同。去度娘找了半个小时,看了各位大神的表述,找到一个比较清晰的文章。

      原来,switch进行了跳转优化,java中对switch有两种处理方式,生成不同的jvm指令,一是tableswitch,一个是lookupswitch。对于case的分支比较密集的情况,如:

    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,得到:

    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:

    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;
            }
     
     
        }
    }
    

    编译为

    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 }
    这个就要挨着查表确定跳转位置了。

      总结:在第一个例子中可以看出使用switch case的时候在匹配条件的时候是直接跳转的,所以效率相对会比if语句中逐个比较会快。而且还有一点是在switch语句中看不到的,第一个switch case语句中会首先判断case值在不在目标值中,如果不在,直接执行default,而不是逐个去比较,全部不符合条件之后再执行default。

    原文出处:http://bbs.csdn.net/topics/300023354

    原作者:ZangXT

     

  • 相关阅读:
    linux 服务发布脚本升级,远程发布,指定拉取远程dev,test等分支代码
    linux 执行脚本1.补充命令 2.后台执行
    centos7 操作防火墙
    复制目录及其子目录下所有文件DOC
    总结
    nmon监控与 nmon analyser分析
    nginx配置文服
    单字段去重 distinct 返回其他多个字段
    二维数组怎样进行遍历
    Socket与URL通信比较
  • 原文地址:https://www.cnblogs.com/sxzwj/p/6046948.html
Copyright © 2011-2022 走看看