您的位置:首页 > 其它

为什么switch的效率要比 if else 高?

2015-11-10 10:35 246 查看

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: