检查 Java 中是否存在枚举

2022-08-31 13:34:29

是否可以通过将枚举与给定字符串进行比较来检查枚举是否存在?我似乎找不到任何这样的功能。我可以尝试使用该方法并捕获异常,但我被教导捕获运行时异常不是很好的做法。有人有什么想法吗?valueOf


答案 1

如果我需要这样做,我有时会建立一个名字,甚至是我自己的名字 - 那么你可以检查一下。Set<String>Map<String,MyEnum>

有几点值得注意:

  • 在静态初始值设定项中填充任何此类静态集合。不要使用变量初始值设定项,然后依赖于它在枚举构造函数运行时已经执行 - 它不会是!(枚举构造函数是首先要执行的内容,在静态初始值设定项之前。
  • 尽量避免频繁使用 - 每次都必须创建并填充一个新数组。要迭代所有元素,请使用EnumSet.allOf,这对于没有大量元素的枚举要有效得多。values()

示例代码:

import java.util.*;

enum SampleEnum {
    Foo,
    Bar;

    private static final Map<String, SampleEnum> nameToValueMap =
        new HashMap<String, SampleEnum>();
    
    static {
        for (SampleEnum value : EnumSet.allOf(SampleEnum.class)) {
            nameToValueMap.put(value.name(), value);
        }
    }
    
    public static SampleEnum forName(String name) {
        return nameToValueMap.get(name);
    }
}

public class Test {
    public static void main(String [] args)
        throws Exception { // Just for simplicity!
        System.out.println(SampleEnum.forName("Foo"));
        System.out.println(SampleEnum.forName("Bar"));
        System.out.println(SampleEnum.forName("Baz"));
    }
}

当然,如果你只有几个名字,这可能有点过分了 - 当n足够小时,O(n)解决方案通常会胜过O(1)解决方案。这是另一种方法:

import java.util.*;

enum SampleEnum {
    Foo,
    Bar;

    // We know we'll never mutate this, so we can keep
    // a local copy.
    private static final SampleEnum[] copyOfValues = values();
    
    public static SampleEnum forName(String name) {
        for (SampleEnum value : copyOfValues) {
            if (value.name().equals(name)) {
                return value;
            }
        }
        return null;
    }
}

public class Test {
    public static void main(String [] args)
        throws Exception { // Just for simplicity!
        System.out.println(SampleEnum.forName("Foo"));
        System.out.println(SampleEnum.forName("Bar"));
        System.out.println(SampleEnum.forName("Baz"));
    }
}

答案 2

我不认为有一种内置的方法可以在不捕获异常的情况下做到这一点。你可以改用类似这样的东西:

public static MyEnum asMyEnum(String str) {
    for (MyEnum me : MyEnum.values()) {
        if (me.name().equalsIgnoreCase(str))
            return me;
    }
    return null;
}

编辑:正如 Jon Skeet 所指出的,每次调用私有支持数组时,它的工作原理都是克隆一个私有支持阵列。如果性能至关重要,则可能只想调用一次,缓存数组,然后循环访问该数组。values()values()

此外,如果您的枚举具有大量值,则 Jon Skeet 的映射替代方案可能比任何数组迭代都表现得更好。