присвоить - сравнение enum java
Как получить значение перечисления из строкового значения в Java? (16)
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;
}
}
Скажем, у меня есть перечисление, которое просто
public enum Blah {
A, B, C, D
}
и я хотел бы найти значение перечисления строки, например "A"
которое будет Blah.A
Как это можно сделать?
Enum.valueOf()
ли метод Enum.valueOf()
? Если да, то как я буду использовать это?
Библиотека commons-lang Apache имеет статическую функцию org.apache.commons.lang3.EnumUtils.getEnum которая будет отображать строку в ваш тип Enum. Тот же ответ по существу, что и Geoffreys, но зачем катиться самостоятельно, когда он уже находится в дикой природе.
В Java 8 статический шаблон карты еще проще и мой предпочтительный метод. Если вы хотите использовать 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);
}
}
Вам может понадобиться следующее:
public enum ObjectType {
PERSON("Person");
public String parameterName;
ObjectType(String parameterName) {
this.parameterName = parameterName;
}
public String getParameterName() {
return this.parameterName;
}
//From String method 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, он вернет вам значение Enum, то есть «Person»,
Вот полезная утилита, которую я использую:
/**
* A common method for all enums since they can't have another base class
* @param <T> Enum type
* @param c enum type. All enums must be all caps.
* @param string case insensitive
* @return corresponding enum, or null
*/
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
if( c != null && string != null ) {
try {
return Enum.valueOf(c, string.trim().toUpperCase());
} catch(IllegalArgumentException ex) {
}
}
return null;
}
Затем в моем классе enum я обычно сохраняю некоторую типизацию:
public static MyEnum fromString(String name) {
return getEnumFromString(MyEnum.class, name);
}
Если ваши перечисления не все шапки, просто измените строку Enum.valueOf
.
Слишком плохо, я не могу использовать T.class
для Enum.valueOf
поскольку T
стирается.
Вы также должны быть осторожны с вашим делом. Позвольте мне объяснить: выполнение Blah.valueOf("A")
работает, но Blah.valueOf("a")
не будет работать. Затем снова будет Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
.
редактировать
Изменен toUpperCase
на toUpperCase(Locale.ENGLISH)
на основе tc. комментарий и java-документы
edit2 На андроиде вы должны использовать Locale.US
, как указывает сулай .
Добавляя к высокому рейтингу ответ, с полезной утилитой ...
valueOf()
выбрасывает два разных Исключения в случаях, когда ему не нравится его ввод.
-
IllegalArgumentException
-
NullPointerExeption
Если ваши требования таковы, что у вас нет гарантии, что ваша строка определенно будет соответствовать значению перечисления, например, если данные String поступают из базы данных и могут содержать старую версию перечисления, тогда вам нужно будет обрабатывать эти довольно часто...
Итак, вот метод многократного использования, который я написал, который позволяет нам определить возвращаемый по умолчанию Enum, если String, который мы передаем, не соответствует.
private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
try {
return Enum.valueOf(defaultVal.getDeclaringClass() , name);
} catch (IllegalArgumentException | NullPointerException e) {
return defaultVal;
}
}
Используйте его так:
public enum MYTHINGS {
THINGONE,
THINGTWO
}
public static void main(String [] asd) {
valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}
Другая утилита записывается обратным образом. Используя значение, которое идентифицирует Enum, а не его имя.
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;
public class EnumUtil {
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose a
* public method return value of this Enum is
* equal to <code>valor</code>.<br/>
* Such method should be unique public, not final and static method
* declared in Enum.
* In case of more than one method in match those conditions
* its first one will be chosen.
*
* @param enumType
* @param value
* @return
*/
public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
String methodName = getMethodIdentifier(enumType);
return from(enumType, value, methodName);
}
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose
* public method <code>methodName</code> return is
* equal to <code>value</code>.<br/>
*
* @param enumType
* @param value
* @param methodName
* @return
*/
public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
EnumSet<E> enumSet = EnumSet.allOf(enumType);
for (E en : enumSet) {
try {
String invoke = enumType.getMethod(methodName).invoke(en).toString();
if (invoke.equals(value.toString())) {
return en;
}
} catch (Exception e) {
return null;
}
}
return null;
}
private static String getMethodIdentifier(Class<?> enumType) {
Method[] methods = enumType.getDeclaredMethods();
String name = null;
for (Method method : methods) {
int mod = method.getModifiers();
if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
name = method.getName();
break;
}
}
return name;
}
}
Пример:
public enum Foo {
ONE("eins"), TWO("zwei"), THREE("drei");
private String value;
private Foo(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
EnumUtil.from(Foo.class, "drei")
возвращает Foo.THREE
, потому что он будет использовать getValue
для соответствия «drei», который является уникальным публичным, а не конечным, а не статическим методом в Foo. В случае, если Foo имеет больше, чем публичный, а не конечный и не статический метод, например, getTranslate
который возвращает «drei», можно использовать другой метод: EnumUtil.from(Foo.class, "drei", "getTranslate")
.
Другой способ сделать это, используя неявное статическое name()
метода name()
для Enum. 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
вдохновение: 10 примеров Enum в Java
Если вы не хотите писать свою собственную утилиту, используйте библиотеку guava Google:
Enums.getIfPresent(Blah.class, "A")
В отличие от встроенной функции java, давайте проверим, присутствует ли A в Blah и не генерирует исключение.
Как насчет?
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value){
try{
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e){
return Optional.empty();
}
}
}
Мне нравится использовать этот процесс для анализа команд как строк в перечислениях. Обычно у меня есть одно из перечислений как «неизвестное», поэтому оно помогает вернуть это, когда другие не найдены (даже на основе без учета регистра), а не в нуле (это означает, что нет значения). Поэтому я использую этот подход.
static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
Enum<E> unknown=null;
for (Enum<E> enumVal: enumClass.getEnumConstants()) {
if (what.compareToIgnoreCase(enumVal.name()) == 0) {
return enumVal;
}
if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
unknown=enumVal;
}
}
return unknown;
}
Поскольку switch
-version еще не упоминается, я ввожу его (повторное использование перечисления OP):
private enum Blah {
A, B, C, D;
public static Blah byName(String name) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
throw new IllegalArgumentException(
"No enum constant " + Blah.class.getCanonicalName() + "." + name);
}
}
}
Поскольку это не дает никакого дополнительного значения методу valueOf(String name)
, имеет смысл только определить дополнительный метод, если мы хотим иметь другое поведение. Если мы не хотим поднимать IllegalArgumentException
мы можем изменить реализацию:
private enum Blah {
A, B, C, D;
public static Blah valueOfOrDefault(String name, Blah defaultValue) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
if (defaultValue == null) {
throw new NullPointerException();
}
return defaultValue;
}
}
}
Предоставляя значение по умолчанию, мы сохраняем contract Enum.valueOf(String name)
не бросая IllegalArgumentException
таким образом, чтобы ни в коем случае не возвращался null
. Поэтому мы бросаем NullPointerException
если имя имеет значение null
и в случае default
если defaultValue
равно null
. Вот как работает valueOfOrDefault
.
Этот подход использует дизайн Map
-Interface, который предоставляет метод Map.getOrDefault(Object key, V defaultValue)
с Java 8.
Решение с использованием библиотек 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();
}
}
Blah.valueOf(string)
использовать Blah.valueOf(string)
но вы также можете использовать Enum.valueOf(Blah.class, string)
.
java.lang.Enum
определяет несколько полезных методов, которые доступны для всех типов перечисления в Java:
- Вы можете использовать метод
name()
для получения имен любых констант Enum. Строковым литералом, используемым для записи констант перечисления, является их имя. - Аналогично метод
values()
может использоваться для получения массива всех констант Enum из типа Enum. - И для заданного вопроса вы можете использовать метод
valueOf()
для преобразования константы String в Enum в Java, как показано ниже.
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()
возвращает константу Enum Gender.MALE, вызывающее имя на которой возвращает "MALE"
.