java - compare enum with string c#




Comprobar si enum existe en Java (6)

¿Hay alguna forma de verificar si existe una enumeración comparándola con una cadena dada? Parece que no puedo encontrar ninguna de esas funciones. Podría intentar usar el método valueOf y atrapar una excepción, pero me han enseñado que la captura de excepciones de tiempo de ejecución no es una buena práctica. ¿Alguien tiene ideas?


Basado en la respuesta de Jon Skeet, hice una clase que me permite hacerlo fácilmente en el trabajo:

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * This permits to easily implement a failsafe implementation of the enums's valueOf
 * Better use it inside the enum so that only one of this object instance exist for each enum...
 * (a cache could solve this if needed)
 * </p>
 *
 * <p>
 * Basic usage exemple on an enum class called MyEnum:
 *
 *   private static final FailSafeValueOf<MyEnum> FAIL_SAFE = FailSafeValueOf.create(MyEnum.class);
 *   public static MyEnum failSafeValueOf(String enumName) {
 *       return FAIL_SAFE.valueOf(enumName);
 *   }
 *
 * </p>
 *
 * <p>
 * You can also use it outside of the enum this way:
 *   FailSafeValueOf.create(MyEnum.class).valueOf("EnumName");
 * </p>
 *
 * @author Sebastien Lorber <i>([email protected])</i>
 */
public class FailSafeValueOf<T extends Enum<T>> {

    private final Map<String,T> nameToEnumMap;

    private FailSafeValueOf(Class<T> enumClass) {
        Map<String,T> map = Maps.newHashMap();
        for ( T value : EnumSet.allOf(enumClass)) {
            map.put( value.name() , value);
        }
        nameToEnumMap = ImmutableMap.copyOf(map);
    }

    /**
     * Returns the value of the given enum element
     * If the 
     * @param enumName
     * @return
     */
    public T valueOf(String enumName) {
        return nameToEnumMap.get(enumName);
    }

    public static <U extends Enum<U>> FailSafeValueOf<U> create(Class<U> enumClass) {
        return new FailSafeValueOf<U>(enumClass);
    }

}

Y la prueba de la unidad:

import org.testng.annotations.Test;

import static org.testng.Assert.*;


/**
 * @author Sebastien Lorber <i>([email protected])</i>
 */
public class FailSafeValueOfTest {

    private enum MyEnum {
        TOTO,
        TATA,
        ;

        private static final FailSafeValueOf<MyEnum> FAIL_SAFE = FailSafeValueOf.create(MyEnum.class);
        public static MyEnum failSafeValueOf(String enumName) {
            return FAIL_SAFE.valueOf(enumName);
        }
    }

    @Test
    public void testInEnum() {
        assertNotNull( MyEnum.failSafeValueOf("TOTO") );
        assertNotNull( MyEnum.failSafeValueOf("TATA") );
        assertNull( MyEnum.failSafeValueOf("TITI") );
    }

    @Test
    public void testInApp() {
        assertNotNull( FailSafeValueOf.create(MyEnum.class).valueOf("TOTO") );
        assertNotNull( FailSafeValueOf.create(MyEnum.class).valueOf("TATA") );
        assertNull( FailSafeValueOf.create(MyEnum.class).valueOf("TITI") );
    }

}

Tenga en cuenta que utilicé Guava para hacer una ImmutableMap, pero en realidad podría usar un mapa normal, ya que el mapa nunca se devuelve ...


Desde Java 8, podríamos usar streams lugar de bucles for. Además, podría ser apropiado devolver un Optional si la enumeración no tiene una instancia con ese nombre.

He encontrado las siguientes tres alternativas sobre cómo buscar una enumeración:

private enum Test {
    TEST1, TEST2;

    public Test fromNameOrThrowException(String name) {
        return Arrays.stream(values())
                .filter(e -> e.name().equals(name))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("No enum with name " + name));
    }

    public Test fromNameOrNull(String name) {
        return Arrays.stream(values()).filter(e -> e.name().equals(name)).findFirst().orElse(null);
    }

    public Optional<Test> fromName(String name) {
        return Arrays.stream(values()).filter(e -> e.name().equals(name)).findFirst();
    }
}

No creo que haya una forma incorporada de hacerlo sin detectar excepciones. En su lugar, podría usar algo como esto:

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

Editar: Como señala Jon Skeet, values() funciona clonando una matriz de respaldo privada cada vez que se invoca. Si el rendimiento es crítico, puede llamar a values() solo una vez, almacenar en caché la matriz e iterar a través de eso.

Además, si su enumeración tiene una gran cantidad de valores, es probable que la alternativa del mapa de Jon Skeet rinda mejor que cualquier iteración de matriz.


No sé por qué alguien te dijo que atrapar excepciones de tiempo de ejecución era malo.

Use valueOf y catch IllegalArgumentException está bien para convertir / verificar una cadena en una enumeración.


También puedes usar guayaba y hacer algo como esto:

// This method returns enum for a given string if it exists, otherwise it returns default enum.
private MyEnum getMyEnum(String enumName) {
  // It is better to return default instance of enum instead of null
  return hasMyEnum(enumName) ? MyEnum.valueOf(enumName) : MyEnum.DEFAULT;
}

// This method checks that enum for a given string exists.
private boolean hasMyEnum(String enumName) {
  return Iterables.any(Arrays.asList(MyEnum.values()), new Predicate<MyEnum>() {
    public boolean apply(MyEnum myEnum) {
      return myEnum.name().equals(enumName);
    }
  }); 
}

En el segundo método, uso la biblioteca de guayaba ( Google Guava ) que proporciona una clase muy útil de Iterables . Usando el método Iterables.any () podemos verificar si existe un valor dado en un objeto de lista. Este método necesita dos parámetros: una lista y un objeto Predicado . Primero utilicé el método Arrays.asList () para crear una lista con todas las enumeraciones. Después de eso, creé un nuevo objeto Predicate que se usa para verificar si un elemento dado (enum en nuestro caso) satisface la condición en el método apply . Si eso sucede, el método Iterables.any () devuelve el valor verdadero.


Una de mis lib favoritas: Apache Commons.

EnumUtils puede hacer eso fácilmente.

Siguiendo un ejemplo para validar un Enum con esa biblioteca:

MyEnum strTypeEnum = null;

// test if String str is compatible with the enum 
if( EnumUtils.isValidEnum(MyEnum.class, str) ){
    strTypeEnum = MyEnum.valueOf(str);
}




compare