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

发布于 2024-07-26 06:53:42 字数 424 浏览 4 评论 0原文

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

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

I would like to lookup an enum from its string value (or possibly any other value). I've tried the following code but it doesn't allow static in initialisers. Is there a simple way?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

青萝楚歌 2024-08-02 06:53:42

使用为每个 Enum 自动创建的 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 个枚举值,几乎不值得任何其他努力,事实上,除非你有很多值,否则我不会费心使用 Map,它会足够快。

Use the valueOf method which is automatically created for each Enum.

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

For arbitrary values start with:

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

Only move on later to Map implementation if your profiler tells you to.

I know it's iterating over all the values, but with only 3 enum values it's hardly worth any other effort, in fact unless you have a lot of values I wouldn't bother with a Map it'll be fast enough.

扭转时空 2024-08-02 06:53:42

你很接近了。 对于任意值,请尝试如下操作:

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

You're close. For arbitrary values, try something like the following:

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);
    }
}
酷遇一生 2024-08-02 06:53:42

使用 Java 8,您可以通过以下方式实现:

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

with Java 8 you can achieve with this way:

public static Verbosity findByAbbr(final String abbr){
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}
尹雨沫 2024-08-02 06:53:42

@Lyle 的答案相当危险,我发现它不起作用,特别是如果您将枚举设置为静态内部类。 相反,我使用了类似的东西,它将在枚举之前加载 BootstrapSingleton 映射。

编辑 对于现代 JVM(JVM 1.6 或更高版本)来说,这不再是问题,但我确实认为 JRebel 仍然存在问题,但我还没有机会重新测试它< /em>.

首先加载我:

   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,并且(理论上)应该在之前加载。

@Lyle's answer is rather dangerous and I have seen it not work particularly if you make the enum a static inner class. Instead I have used something like this which will load the BootstrapSingleton maps before the enums.

Edit this should not be a problem any more with modern JVMs (JVM 1.6 or greater) but I do think there are still issues with JRebel but I haven't had a chance to retest it.

Load me first:

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

Now load it in the enum constructor:

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

If you have an inner enum you can just define the Map above the enum definition and that (in theory) should get loaded before.

如果没有你 2024-08-02 06:53:42

并且您不能使用 valueOf()

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

And you can't use valueOf()?

Edit: Btw, there is nothing stopping you from using static { } in an enum.

春风十里 2024-08-02 06:53:42

如果它对其他人有帮助,我更喜​​欢的选项(此处未列出)使用 Guava 的地图功能

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

默认情况下,您可以使用 null< /code>,您可以抛出 IllegalArgumentException 或者您的 fromString 可以返回一个Optional,无论您喜欢什么行为。

In case it helps others, the option I prefer, which is not listed here, uses 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);
    }
}

With the default you can use null, you can throw IllegalArgumentException or your fromString could return an Optional, whatever behavior you prefer.

哽咽笑 2024-08-02 06:53:42

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

private static Map<String, Verbosity> stringMap = Arrays.stream(values())
                 .collect(Collectors.toMap(Enum::toString, Function.identity()));

since java 8 you can initialize the map in a single line and without static block

private static Map<String, Verbosity> stringMap = Arrays.stream(values())
                 .collect(Collectors.toMap(Enum::toString, Function.identity()));
娇俏 2024-08-02 06:53:42
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);
    }
}
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);
    }
}
凉城凉梦凉人心 2024-08-02 06:53:42

也许,看看这个。 它对我有用。
其目的是使用“/red_color”查找“RED”。
如果枚举很多,声明一个静态映射并仅将枚举加载到其中一次会带来一些性能优势。

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

请提出您的意见。

Perhaps, take a look at this. Its working for me.
The purpose of this is to lookup 'RED' with '/red_color'.
Declaring a static map and loading the enums into it only once would bring some performance benefits if the enums are many.

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

Please put in your opinons.

还不是爱你 2024-08-02 06:53:42

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

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

如果您需要辅助值,您只需像其他一些答案一样首先构建查找映射。

If you want a default value and don't want to build lookup maps, you can create a static method to handle that.
This example also handles lookups where the expected name would start with a number.

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

If you need it on a secondary value, you would just build the lookup map first like in some of the other answers.

暖风昔人 2024-08-02 06:53:42

您可以将枚举定义为以下代码:

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

请参阅以下内容更多说明的链接

You can define your Enum as following code :

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

百善笑为先 2024-08-02 06:53:42

您可以按照 Gareth Davis 和 Gareth Davis 的建议使用 Enum::valueOf() 函数。 Brad Mace 位于上面,但请确保您处理了如果所使用的字符串不存在于枚举中则会抛出的 IllegalArgumentException

You can use the Enum::valueOf() function as suggested by Gareth Davis & Brad Mace above, but make sure you handle the IllegalArgumentException that would be thrown if the string used is not present in the enum.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文