如何从String值中查找Java枚举?

时间:2009-07-03 21:29:32

标签: java enums lookup

我想从字符串值(或可能是任何其他值)查找枚举。我尝试了以下代码,但它不允许在初始化程序中使用静态代码。有一个简单的方法吗?

public enum Verbosity {

    BRIEF, NORMAL, FULL;

    private static Map<String, Verbosity> stringMap = new HashMap<String, Verbosity>();

    private Verbosity() {
        stringMap.put(this.toString(), this);
    }

    public static Verbosity getVerbosity(String key) {
        return stringMap.get(key);
    }
};

13 个答案:

答案 0 :(得分:207)

使用为每个枚举自动创建的valueOf方法。

Verbosity.valueOf("BRIEF") == Verbosity.BRIEF

对于任意值,请以:

开头
public static Verbosity findByAbbr(String abbr){
    for(Verbosity v : values()){
        if( v.abbr().equals(abbr)){
            return v;
        }
    }
    return null;
}

如果您的探查器告诉您,只能在以后继续使用Map实现。

我知道它正在迭代所有的值,但只有3个枚举值,它几乎不值得任何其他努力,事实上,除非你有很多值我不会打扰地图它会足够快。 / p>

答案 1 :(得分:121)

你很亲密。对于任意值,请尝试以下内容:

public enum Day { 

    MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
    THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

    private final String abbreviation;

    // Reverse-lookup map for getting a day from an abbreviation
    private static final Map<String, Day> lookup = new HashMap<String, Day>();

    static {
        for (Day d : Day.values()) {
            lookup.put(d.getAbbreviation(), d);
        }
    }

    private Day(String abbreviation) {
        this.abbreviation = abbreviation;
    }

    public String getAbbreviation() {
        return abbreviation;
    }

    public static Day get(String abbreviation) {
        return lookup.get(abbreviation);
    }
}

答案 2 :(得分:15)

用Java 8你可以用这种方式实现:

public static Verbosity findByAbbr(final String abbr){
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}

答案 3 :(得分:13)

@Lyle的答案相当危险,我发现如果你把枚举变成一个静态的内部类,它就不起作用了。相反,我使用了类似的东西,它将在枚举之前加载BootstrapSingleton地图。

编辑 这应该不再是现代JVM(JVM 1.6或更高版本)的问题,但我认为JRebel仍然存在问题,但我没有机会重新测试

先加载我:

   public final class BootstrapSingleton {

        // Reverse-lookup map for getting a day from an abbreviation
        public static final Map<String, Day> lookup = new HashMap<String, Day>();
   }

现在将它加载到枚举构造函数中:

   public enum Day { 
        MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
        THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

        private final String abbreviation;

        private Day(String abbreviation) {
            this.abbreviation = abbreviation;
            BootstrapSingleton.lookup.put(abbreviation, this);
        }

        public String getAbbreviation() {
            return abbreviation;
        }

        public static Day get(String abbreviation) {
            return lookup.get(abbreviation);
        }
    }

如果你有一个内部枚举,你可以在枚举定义之上定义Map,并且(理论上)应该在之前加载。

答案 4 :(得分:6)

你不能使用valueOf()

编辑:顺便说一句,没有什么可以阻止你在枚举中使用静态{}。

答案 5 :(得分:5)

在Java语言规范7中有一个a example!这反映了您对使用自引用初始化地图的问题。

答案 6 :(得分:3)

如果它对其他人有帮助,我更喜​​欢的选项(此处未列出)使用Guava's Maps functionality

public enum Vebosity {
    BRIEF("BRIEF"),
    NORMAL("NORMAL"),
    FULL("FULL");

    private String value;
    private Verbosity(final String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

    private static ImmutableMap<String, Verbosity> reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue);

    public static Verbosity fromString(final String id) {
        return reverseLookup.getOrDefault(id, NORMAL);
    }
}

默认情况下,您可以使用nullthrow IllegalArgumentExceptionfromString可以返回Optional,无论您喜欢什么行为。

答案 7 :(得分:1)

也许,看看这个。它为我工作。 这样做的目的是用'/ red_color'查找'RED'。 如果static map很多,则声明enum并仅将enum加载到其中只会带来一些性能优势。

public class Mapper {

public enum Maps {

    COLOR_RED("/red_color", "RED");

    private final String code;
    private final String description;
    private static Map<String, String> mMap;

    private Maps(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public String getCode() {
        return name();
    }

    public String getDescription() {
        return description;
    }

    public String getName() {
        return name();
    }

    public static String getColorName(String uri) {
        if (mMap == null) {
            initializeMapping();
        }
        if (mMap.containsKey(uri)) {
            return mMap.get(uri);
        }
        return null;
    }

    private static void initializeMapping() {
        mMap = new HashMap<String, String>();
        for (Maps s : Maps.values()) {
            mMap.put(s.code, s.description);
        }
    }
}
}

请提出您的意见。

答案 8 :(得分:0)

您可以将Enum定义为以下代码:

public enum Verbosity 
{
   BRIEF, NORMAL, FULL, ACTION_NOT_VALID;
   private int value;

   public int getValue()
   {
     return this.value;
   } 

   public static final Verbosity getVerbosityByValue(int value)
   {
     for(Verbosity verbosity : Verbosity.values())
     {
        if(verbosity.getValue() == value)
            return verbosity ;
     }

     return ACTION_NOT_VALID;
   }

   @Override
   public String toString()
   {
      return ((Integer)this.getValue()).toString();
   }
};

See following link for more clarification

答案 9 :(得分:0)

从Java 8开始,您可以在一行中初始化地图,而无需使用静态块

extension UITextField {
open override func awakeFromNib() {
        super.awakeFromNib()
        if UserDefaults.languageCode == "ar" {
            if textAlignment == .natural {
                self.textAlignment = .right
            }
        }
    }
}

答案 10 :(得分:-1)

如果您想要默认值并且不想构建查找映射,则可以创建一个静态方法来处理它。 此示例还处理期望名称以数字开头的查找。

    public static final Verbosity lookup(String name) {
        return lookup(name, null);
    }

    public static final Verbosity lookup(String name, Verbosity dflt) {
        if (StringUtils.isBlank(name)) {
            return dflt;
        }
        if (name.matches("^\\d.*")) {
            name = "_"+name;
        }
        try {
            return Verbosity.valueOf(name);
        } catch (IllegalArgumentException e) {
            return dflt;
        }
    }

如果您需要一个辅助值,则只需像其他一些答案中一样先构建查找图即可。

答案 11 :(得分:-1)

public enum EnumRole {

ROLE_ANONYMOUS_USER_ROLE ("anonymous user role"),
ROLE_INTERNAL ("internal role");

private String roleName;

public String getRoleName() {
    return roleName;
}

EnumRole(String roleName) {
    this.roleName = roleName;
}

public static final EnumRole getByValue(String value){
    return Arrays.stream(EnumRole.values()).filter(enumRole -> enumRole.roleName.equals(value)).findFirst().orElse(ROLE_ANONYMOUS_USER_ROLE);
}

public static void main(String[] args) {
    System.out.println(getByValue("internal role").roleName);
}

}

答案 12 :(得分:-3)

您可以使用Gareth Davis&amp; Brad Mace上面,但是如果enum中没有使用的字符串,请确保处理将被抛出的Enum::valueOf()