如何在Java中通过字符串值获取枚举值

2365

假设我有一个枚举类型,内容如下:

public enum Blah {
    A, B, C, D
}

我想要根据一个字符串找到对应的枚举值,例如 "A" 对应的是 Blah.A。有什么方法可以实现吗?

Enum.valueOf() 是我需要的方法吗?如果是,我该如何使用它?


1
这里有一个解决方案,不仅可以忽略大小写地执行此操作,而且将解决方案从O(N)移动到O(1):https://dev59.com/Ll4c5IYBdhLWcg3wFW6N#74408971 - chaotic3quilibrium
32个回答

17

您可能需要这样做:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    // From the String method, it will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

再加一个

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

这将通过枚举名称的字符串返回值。例如,如果您在fromEnumName中提供了“PERSON”,它将返回Enum的值,即“Person”。


15

另一种方法是使用Enum的隐式静态方法name()name将返回创建该枚举时使用的确切字符串,可以用于根据提供的字符串进行检查:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

测试:

System.out.println(Blah.getEnum("B").name());


// It will print B  B

Inspiration: 10个Java中枚举的例子


14

在Java 8中,静态Map模式甚至更加简单,也是我首选的方法。如果您想要将Enum与Jackson一起使用,可以重写toString并使用该方法代替名称,然后用@JsonValue进行注释。

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

    MyEnumForJson(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}

混淆代码比赛的亚军?我的意思是,从技术上讲这是正确的。 :-) ... 但对于一个简单的 for/next 循环遍历 Map 来说,它是不必要的晦涩 - 这与 Java 的早期版本提供的实现并没有什么区别。private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity())); - Darrell Teague
1
我认为当你习惯了for循环时,流似乎很难理解,但每个人都有自己的喜好。 - Novaterata

12

以下是使用Guava库的解决方案。方法getPlanet()不区分大小写,因此getPlanet("MerCUrY")将返回Planet.MERCURY。

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}

11

枚举类型非常有用。我经常使用 Enum 来为不同语言的一些字段添加描述,例如下面这个例子:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

然后您可以根据传递给getDescription(String lang)方法的语言代码动态检索描述,例如:

String statusDescription = Status.valueOf("ACT").getDescription("en");

9
为了补充之前的回答,并解决一些关于null和NPE的讨论,我使用GuavaOptionals来处理不存在/无效的情况。这对URI和参数解析非常有用。
public enum E {
    A,B,C;
    public static Optional<E> fromString(String s) {
        try {
            return Optional.of(E.valueOf(s.toUpperCase()));
        } catch (IllegalArgumentException|NullPointerException e) {
            return Optional.absent();
        }
    }
}

对于那些不了解的人,这里有一些关于避免null的更多信息,使用Optional


9

8

这是一种受Thrift生成代码启发的O(1)方法,它使用哈希表。

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}

6
public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}

6

java.lang.Enum定义了几个有用的方法,可用于Java中的所有枚举类型:

  • 您可以使用name()方法获取任何Enum常量的名称。用于编写枚举常量的字符串文字是它们的名称。
  • 同样,values()方法可用于从Enum类型获取所有Enum常量的数组。
  • 对于所提问的问题,您可以使用valueOf()方法将任何String转换为Java中的Enum常量,如下所示。
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

在这段代码片段中,valueOf() 方法返回一个枚举常量,Gender.MALE,并调用其 name 属性返回 "MALE"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接