Java Enum valueOf效率

too*_*kit 10 java enums

您认为哪种效率更高?

使用'WeekDay'只是一个例子:

public enum WeekDay {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY;
}
Run Code Online (Sandbox Code Playgroud)

循环并首先验证日期字符串:

public void parseString(String line) {
    String[] tokens = line.split();
    String day = tokens[1]; // day 'should' always be a weekday
    if (isValidWeekDay(day)) {
        WeekDay weekDay = WeekDay.valueOf(day); // won't throw exception
        ...
    } else {
        throw new InvalidWeekDayException(day); // subclass of RuntimeException
    }
}
private boolean isValidWeekDay(String day) {
    for (WeekDay weekDay : WeekDay.values()) {
        if(weekDay.toString().equals(day))
           return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

或者因为在99.99%的情况下,一天是正确的:

public void parseString(String line) {
    String[] tokens = line.split();
    String day = tokens[1]; // day 'should' always be a weekday
    try {
        WeekDay weekDay = WeekDay.valueOf(day); // might throw exception
        ...
    } catch (IllegalArgumentException e) {
        throw new InvalidWeekDayException(day, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

为了澄清,输入字符串将来自客户端应用程序,而不是用户.换句话说,在这个例子中收到非工作日会是一个错误.

Kev*_*Day 8

第二种方法的性能问题是什么?抓住这样的例外几乎没有任何成本.从设计角度来看,使用异常进行正常控制流通常是一个坏主意,这是性能考虑的日子早已不复存在.在调试器中,使用异常作为重要的控制操作会使事情减慢大约10倍.但这会被JIT优化,并且在生产中没有可测量的影响.

这些数字是基于我对zxing项目进行评估的经验,该项目使用了各种流量控制的例外情况.当我第一次看到它时,我感到震惊.我仍然认为这不是最好的设计,但我做了相当多的测试,可以肯定地说它对性能没有实际影响.这是一种在整个地方使用异常进行流量控制的算法.您的情况,即异常只会在非常特殊的情况下被抛出,这是一个非问题.

编辑:我的回答中有一两个问题,我想确保我对我所说的内容非常清楚:我不认为对正常控制流使用异常是个好主意.仅仅因为性能不是不使用异常的好方法,这并不意味着没有其他完全正确的原因(例如可读性,可测试性,可扩展性).在OP的情况下,绝对要求使用异常,并且肯定不会导致任何类型的性能问题.


Rob*_*bin 6

正如已经评论过的那样,您必须进行剖析才能确定.即使在您自己的解析方法中,您也可以通过在解析列表时返回枚举来加快速度.

private WeekDay getValidWeekDay(String day) {
    for (WeekDay weekDay : WeekDay.values()) {
        if(weekDay.toString().equals(day))
           return weekDay;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

除非这是一个时间关键的应用程序,否则我不会在任何一种情况下担心它,只需采用最易读的方法.我认为这将使用WeekDay.valueOf()方法.

如果您不想处理异常,那么在枚举中创建一个值的Map,并从查找中有效地执行valueOf(),如果找不到则返回null.

public enum WeekDay {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY;

    private static Map<String, WeekDay> valueMap;

    public static WeekDay getValue(String possibleName)
    {
        if (valueMap == null)
        {
            valueMap = new HashMap<String, WeekDay>();
            for(WeedDay day: values())
                valueMap.put(day.toString(), day);
        }
        return valueMap.get(possibleName);

    }
 }
Run Code Online (Sandbox Code Playgroud)

这实际上是valueOf()方法正在做的事情,除非它在找不到时抛出IllegalArgumentException.这种方法只会返回null,因此不会生成堆栈跟踪.


小智 6

我知道这是一个老帖子,但我相信以下结果仍然很有趣.我运行10000000个测试来查找enum ENUM {FIRST, SECOND, THIRD, FOURTH, LAST}使用JDK 1.8 的元素.下表显示了简单循环所需的时间valueOf().

text     loop   valueOf  ratio
------------------------------
"FIRST"  121    65       186%
"LAST"   188    57       330%
"foo"    155    8958     1.7%

结论 - valueOf()如果我希望值与枚举不匹配,我就不会使用.