Java Enum.valueOf() efficiency when value does not exist

后端 未结 7 3455
深忆病人
深忆病人 2021-02-20 17:58

Which would you consider more efficient?

The use of \'WeekDay\' is just an example:

public enum WeekDay {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDA         


        
相关标签:
7条回答
  • 2021-02-20 18:33

    What is the performance concern about the 2nd approach? Catching an exception like that costs almost nothing. Using exceptions for normal control flow is generally a bad idea from a design perspective, the days where this was a performance consideration are long gone. In a debugger, using exceptions as significant control operations will slow things down by a factor of about 10. But this gets optimized by the JIT and there is no measurable impact in production.

    These numbers are based on experience with an evaluation I did of the zxing project, which uses exceptions for all sorts of flow control. When I first saw it, I was horrified. I still think it's not the best design, but I did quite a bit of testing and can say with a good bit of confidence that it had no real impact on performance. And this is an algorithm that was using exceptions all over the place for flow control. Your situation, where the exception will only get thrown in highly exceptional circumstances, is a non issue.

    Edit: I've had a downvote or two on my answer, and I want to make sure that I'm super clear on what I'm saying: I do not think that it's a good idea to use exceptions for normal control flow. Just because performance is not a good argument for not using exceptions this way doesn't mean that there aren't other, perfectly valid reasons (such as readability, testability, extendability). In the case of the OP, the use of an exception is absolutely called for, and definitely wouldn't cause any sort of performance issue.

    0 讨论(0)
  • 2021-02-20 18:35

    Store the valid strings in a HashSet, and decide whether a string is a valid day or not based on Set.contains(...).

    The set can be a static final Set, and you can wrap in an unmodifiable for good measure:

    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);
    }
    
    0 讨论(0)
  • 2021-02-20 18:39

    As has been commented, you will have to profile to find out for sure. Even in your own parsing approach, you can make it faster by returning the enum when you parse the list.

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

    Unless this is a time critical piece of an application, I wouldn't worry about it in either case and simply take the most readable approach. I think that would be using the WeekDay.valueOf() method.

    If you would rather not have to deal with exceptions, then create a Map of your values within the enum and effectively do the equivalent of valueOf() from a lookup which returns null if it is not found.

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

    This is effectively what the valueOf() method is doing anyway, except it throws the IllegalArgumentException when it is not found. This approach will simply return null, thus not generating the stacktrace.

    0 讨论(0)
  • 2021-02-20 18:42

    The loop doesn't do anything that calling valueof doesn't, they have the same functionality : checking whether your string is valid enum. What do you think you gain from the first option ?

    The second option is best:

     try {
         WeekDay weekDay = WeekDay.valueOf(day); // might throw exception
            ...
        } catch (IllegalArgumentException e) {
            throw new InvalidWeekDayException(day);
        }
    
    0 讨论(0)
  • 2021-02-20 18:43

    Or you could create a lookup of enum values inside your enum when the class first loads(see static modifier) and validate using get() as shown below:

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

    Let me know if you need more details

    0 讨论(0)
  • 2021-02-20 18:45

    If your question is really about the efficiency of searching among 7 item you have already wasted too much time on it. Even the fastest search algorithms yield zero or negative benefits until N > 15 or so, other than the O(1) one.

    0 讨论(0)
提交回复
热议问题