【问题标题】:Why is if-else for String faster than switch-case for enum?为什么 String 的 if-else 比 enum 的 switch-case 快?
【发布时间】:2013-05-23 20:14:52
【问题描述】:

由于 Java 6 没有 Stringswitch-case,我经常使用枚举将 if-else 块更改为 switch-case,如下面的代码所示.然而,当我尝试检查这两个替代方案的性能时,我发现 switch-case 比 if-else 替代方案慢,这与我的预期相反。以下是我为下面的代码得到的一些结果

Iterations  If-Else   Switch-Case
1           11810      1609181
10           8214      1059115
100         24141      1152494
1000           183975      1580605
10000         4452698      8710648
100000        7069243     19457585

package conditionals;

import java.util.Random;


public class StringConditionalCheck {

    private static int ifElseCounter = 0;
    private static int switchCaseCounter = 0;

    private static final String first = "First";
    private static final String second = "Second";
    private static final String third = "Third";
    private static final String fourth = "Fourth";

    enum StringOptions {
        First, Second, Third, Fourth
    }

    public static void main(String[] args) {
        final int iterations = Integer.parseInt(args[0]);
        String[] userInputs = generateUserInputs(iterations);

        // Using if-else
        long ifelseStartTime = System.nanoTime();       
        for(int i=0; i<iterations; i++){
            useIfElse(userInputs[i]);
        }       
        long ifelseEndTime = System.nanoTime();
        long ifElseDuration = ifelseEndTime - ifelseStartTime;


        long switchcaseStartTime = System.nanoTime();
        for(int i=0; i<iterations; i++){
            useSwitchCase(userInputs[i]);
        }
        long switchcaseEndTime = System.nanoTime();     
        //just to verify that both options had the same result.
        long switchcaseDuration = switchcaseEndTime - switchcaseStartTime;
        System.out.println(iterations + " " + ifElseDuration + " " + switchcaseDuration + " " + ifElseCounter + " " + switchCaseCounter);
    }

    private static String[] generateUserInputs(int numberOfInputs) {
        String[] generatedInputs = new String[numberOfInputs];
        String[] inputsToChooseFrom = new String[]{first, second, third, fourth};
        Random r = new Random();
        for (int i = 0; i < numberOfInputs; i++) {
            int choice = r.nextInt(4);
            generatedInputs[i] = inputsToChooseFrom[choice];
        }
        return generatedInputs;
    }

    public static void useSwitchCase(String input) {
        StringOptions option = StringOptions.valueOf(input);
        switch(option){

        case First:
            switchCaseCounter += 1;
            break;

        case Second:
            switchCaseCounter += 2;
            break;

        case Third:
            switchCaseCounter += 3;
            break;

        case Fourth:
            switchCaseCounter += 4;
            break;          
        }
    }

    public static void useIfElse(String input) {
        if(input.equals("First")){
            ifElseCounter += 1; 
        }else if(input.equals("Second")){
            ifElseCounter += 2;
        }else if(input.equals("Third")){
            ifElseCounter += 3;
        }else if(input.equals("Fourth")){
            ifElseCounter += 4;
        }
    }
}

造成这种差异的原因是什么?我原以为if-else 会更慢,因为平均会有更多的比较。

【问题讨论】:

标签: string if-statement switch-statement java-6


【解决方案1】:

因为你 99% 的时间都花在了 StringOptions option = StringOptions.valueOf(input);,而不是 switch

【讨论】:

  • 哎呀!完全错过了:P
【解决方案2】:

根据源代码,StringOptions.valueOf 调用做了一些复杂的事情,包括每次调用都构建一个 HashMap,而 String.equals 只是循环遍历字符串一次。

Enum.valueOf(调用Enum.getConstantDirectory)的源代码与String.equals进行比较。

【讨论】:

  • 只是一个小修正。它不会在每次调用时构建HashMap,仅在第一次调用时构建。但是,是的,我看到它在返回结果之前做了几个操作。
猜你喜欢
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 2012-06-02
  • 2011-11-09
  • 2015-04-05
相关资源
最近更新 更多