您认为哪种效率更高?
使用'WeekDay'只是一个例子:
public enum WeekDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY;
}
循环并首先验证日期字符串:
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;
}
或者因为在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);
}
}
更新:
为了澄清,输入字符串将来自客户端应用程序,而不是用户。换句话说,在这个例子中收到非工作日会是一个错误。
答案 0 :(得分:8)
第二种方法的性能问题是什么?抓住这样的例外几乎没有任何成本。从设计角度来看,使用异常进行正常控制流通常是一个坏主意,这是性能考虑的日子早已不复存在。在调试器中,使用异常作为重要的控制操作会使事情减慢约10倍。但这会被JIT优化,并且在生产中没有可测量的影响。
这些数字是基于我对zxing项目进行评估的经验,该项目使用了各种流量控制的例外情况。当我第一次看到它时,我感到震惊。我仍然认为这不是最好的设计,但我做了相当多的测试,可以肯定地说它对性能没有实际影响。这是一种在整个地方使用异常进行流量控制的算法。你的情况只会在非常特殊的情况下被抛出,这是一个非问题。
编辑:我的回答有一两个问题,我想确保我对我所说的内容非常清楚:我不认为使用异常是正常的控制流。仅仅因为性能不是不使用异常的好方法,这并不意味着没有其他完全正确的原因(例如可读性,可测试性,可扩展性)。在OP的情况下,绝对需要使用异常,并且绝对不会导致任何类型的性能问题。
答案 1 :(得分:6)
正如已经评论过的那样,您必须进行剖析才能确定。即使在您自己的解析方法中,您也可以通过在解析列表时返回枚举来加快速度。
private WeekDay getValidWeekDay(String day) {
for (WeekDay weekDay : WeekDay.values()) {
if(weekDay.toString().equals(day))
return weekDay;
}
return null;
}
除非这是一个时间关键的应用程序,否则在任何一种情况下我都不会担心,只需采用最易读的方法。我认为这将使用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);
}
}
这实际上是valueOf()方法正在做的事情,除非它在找不到时抛出IllegalArgumentException。这种方法只会返回null,因此不会生成堆栈跟踪。
答案 2 :(得分:6)
我知道这是一个旧帖子,但我相信以下结果仍然会很有趣。我运行10000000次测试,使用JDK 1.8在enum ENUM {FIRST, SECOND, THIRD, FOURTH, LAST}
中查找元素。下表显示了简单循环和valueOf()
所需的时间。
text loop valueOf ratio ------------------------------ "FIRST" 121 65 186% "LAST" 188 57 330% "foo" 155 8958 1.7%
结论 - 如果我希望值与枚举不匹配,我就不会使用valueOf()
。
答案 3 :(得分:3)
如果您的问题确实是关于7项目中搜索的效率,那么您已经浪费了太多时间。即使是最快的搜索算法也会产生零或负的好处,直到N> 0。除了O(1)之外,大约15个。
答案 4 :(得分:2)
将有效字符串存储在HashSet
中,并根据Set.contains(...)
确定字符串是否为有效日期。
该集合可以是static final Set
,您可以用不可修改的方式包装以获得良好的衡量标准:
private static final Map<String> WEEKDAY_STRINGS;
static {
HashSet<String> set = new HashSet();
for (WeekDay d : WeekDay.values()) {
set.add(d.toString());
}
WEEKDAY_STRINGS = Collections.unmodifiableSet(set);
}
答案 5 :(得分:2)
循环不执行任何调用valueof的操作,它们具有相同的功能:检查字符串是否有效枚举。您认为从第一个选项中获得了什么?
第二种选择是最好的:
try {
WeekDay weekDay = WeekDay.valueOf(day); // might throw exception
...
} catch (IllegalArgumentException e) {
throw new InvalidWeekDayException(day);
}
答案 6 :(得分:2)
或者,您可以在类首次加载时查看枚举值(请参阅静态修饰符)并使用get()进行验证,如下所示:
private String dayName;
private static final Map<String,Weekday> lookup = new HashMap<String, Weekday>();
static{
for (Weekday day: values()){
lookup.put(day.dayName, d);
}
}
public static Weekday get(String _name){
return lookup.get(_name);
}
如果您需要更多详细信息,请与我们联系