Alex Rivera | Logout

Java enum valueOf() with multiple values?

Asked 2010-11-16T19:10:31.050
52

I have a problem in Java using Enums. I have read the documentation about assigning value parameters to Enums. But, my question is what about multiple values, is it possible?

This what I would like to achieve: I have an Enum for languages. Each language is represented by its name and some shorter aliases (not always, and not always the same number of aliases)

Here is an example:

public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian")
}

Can I just define an Enum like this and get the right enum values by calling Language.valueOf() ???

Edit
Report

2 Answers

18

Mapping a string to a enum value, is typically what the valueOf static method is doing for you. So if you want to accomplish this with the use of synonyms, you will have to develop something similar. Because we cannot override a static method, and I do not think we want to in this case, we will name it differently: fromString should be appropriate.

public enum Language { 
  ENGLISH("eng", "en", "en_GB", "en_US"),   
  GERMAN("de", "ge"),   
  CROATIAN("hr", "cro"),   
  RUSSIAN("ru"),
  BELGIAN("be",";-)");

  static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>(); 
  static { 
    for (Language language:Language.values()) { 
      // ignoring the case by normalizing to uppercase
      ALIAS_MAP.put(language.name().toUpperCase(),language); 
      for (String alias:language.aliases)
        ALIAS_MAP.put(alias.toUpperCase(),language);
    } 
  } 

  static public boolean has(String value) { 
    // ignoring the case by normalizing to uppercase
    return ALIAS_MAP.containsKey(value.toUpperCase());
  } 

  static public Language fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Language language = ALIAS_MAP.get(value.toUpperCase()); 
    if (language == null)
      throw new IllegalArgumentException("Not an alias: "+value); 
    return language; 
  } 

  private List<String> aliases; 
  private Language(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
  } 
} 

As a benefit of this type of implementation we can, as demonstrated, also easily implement the has static method to test if a given alias is part of the enum value set. At the same time, we applied some good naming conventions:

  • the enum values go in uppercase, to indicate that they are
answered 2012-09-30T05:54:35.897
1

Wow, really quick reply :) Thanks guys.

Andy is right. I want to call Language.valueOf("eng") or Language.valueOf("english") and get Language.English as return.

I already have a utility function that does this, but it's not very nice. Switch function that checks string values and return appropriate enum instance.

But there is a lot of code rewriting (I have cca 30-40 languages). And if I want to add a language, I have to add it to enum, and implement a new check in the utility class.

I'll try Flavios approach. Just one question. Your constructor, shouldn't it be?

Language(List<String> values) {
    this.values = Arrays.asList(values);
}
answered 2010-11-16T19:41:37.727

Your Answer