当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何从String值中查找Java枚举?》经验,为你挑选了7个好方法。

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

public enum Verbosity {

    BRIEF, NORMAL, FULL;

    private static Map stringMap = new HashMap();

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

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

Gareth Davis.. 219

使用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个枚举值,这几乎不值得任何其他努力,事实上,除非你有很多值我不打扰地图它会足够快.



1> Gareth Davis..:

使用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个枚举值,这几乎不值得任何其他努力,事实上,除非你有很多值我不打扰地图它会足够快.


此外,对于任意值(第二种情况),考虑抛出`IllegalArgumentException`而不是返回null(*ie*,当没有找到匹配时) - 这就是JDK`Enum.valueOf(..)`如何做到这一点.

2> Lyle..:

你很亲密 对于任意值,请尝试以下操作:

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 lookup = new HashMap();

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


@Adam Gent:下面有一个链接到JLS,其中这个确切的构造作为一个例子.它表示静态初始化从上到下发生:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#d5e12267
由于类加载器问题,此方法将无法可靠地工作.我不推荐它,我已经看到它经常失败,因为在访问之前查找映射没有准备好.您需要将"查找"放在枚举之外或其他类中,以便首先加载.
是现代java喜欢java 8修复了内存模型.如果你因为循环引用而嵌入初始化,那么像jrebel这样的热交换代理仍然会搞砸.

3> 小智..:

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

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



4> Adam Gent..:

@Lyle的回答是相当危险的,我已经看到它不起作用,特别是如果你让enum成为一个静态的内部类.相反,我使用了类似的东西,它将在枚举之前加载BootstrapSingleton地图.

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

首先加载我:

   public final class BootstrapSingleton {

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

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

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


需要界定"危险的",为什么一个内部类实现的问题.它更是一个顶部至底部静态清晰度问题,但有工作的代码在另一个相关答案与链接回到这个问题上枚举实例本身使用静态地图与用户定义的值设置为"get"方法枚举类型.http://stackoverflow.com/questions/604424/lookup-enum-by-string-value
@DarrellTeague最初的问题是由于旧的JVM(1.6版之前)或其他JVM(IBM)或热代码交换程序(JRebel)引起的。在现代JVM中不应发生此问题,因此我可以删除答案。

5> Fredrik..:

你不能使用valueOf()?

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



6> mbonato..:

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



7> Chad Befus..:

为了帮助其他人,我更喜欢的选项(未在此处列出)使用了Guava的Maps功能:

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 reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue);

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

使用默认值,您可以使用null,可以throw IllegalArgumentExceptionfromString可以返回Optional,无论您喜欢哪种行为。

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有