15 votes

Comment vérifier si une chaîne donnée fait partie d'un Enum donné en Java ?

J'ai deux enums différents et je veux être capable d'indiquer si une valeur donnée de donnée fait partie d'une collection d'enum. Voici mon code :

public class Check {
    public enum Filter{SIZE, DATE, NAME};
    public enum Action{COPY, DELETE, REMOVE};

    public boolean isInEnum(String value, Enum e){
        // check if string value is a part of a given enum
        return false;
    }

    public void main(){
        String filter = "SIZE";
        String action = "DELETE";
                // check the strings
        isInEnum(filter, Filter);
        isInEnum(action, Action);
    }
}

eclipse dit que dans les deux dernières lignes "Filter can't be resolved to a variable" mais à part cela, il semble que le paramètre Enum dans la fonction "isInEnum" soit erroné.

Quelque chose ne va pas du tout ici, quelqu'un peut-il m'aider ?

0 votes

Vous avez raison :) l'enum est juste une classe normale, vous ne pouvez pas mentionner son nom comme ça. Les membres d'enum sont des instances de leur enum, pas l'enum dans son ensemble.

21voto

Louis Wasserman Points 67557

La méthode la plus simple (et généralement la plus efficace) est la suivante :

public <E extends Enum<E>> boolean isInEnum(String value, Class<E> enumClass) {
  for (E e : enumClass.getEnumConstants()) {
    if(e.name().equals(value)) { return true; }
  }
  return false;
}

et ensuite vous appelez isInEnum(filter, Filter.class) .

0 votes

Pourquoi pas enumClass.getMethod("valueOf", String.class).invoke(null, value) ?

1 votes

Cela a fait l'affaire, mais la syntaxe est folle il faut apprendre un peu sur ces génériques.

1 votes

@MarkoTopolnik pourquoi utiliser Reflection alors que vous bouclez de toute façon les éléments et que vous pouvez utiliser e.valueOf(value) à la place. Notez également que lorsque vous utilisez valueOf, vous devez attraper IllegalArgumentException si le nom n'existe pas et NullPointerException si la chaîne est nulle

11voto

CheshireCat Points 146

Si l'utilisation de la bibliothèque Apache commons lang3 ne vous dérange pas, vous pouvez utiliser le code suivant :

EnumUtils.isValidEnum(Filter.class, filter)

Selon le docs :

Cette méthode diffère de Enum.valueOf(java.lang.Class, java.lang.String) en ce qu'elle ne lève pas d'exception pour un nom d'enum invalide.

1 votes

Le problème est que pour ajouter un utilitaire trivial, il faut ajouter une nouvelle dépendance... les dépendances sont coûteuses... c'est comme acheter une voiture juste parce qu'on a trouvé une clé de voiture...

1 votes

@Stunner Assez juste, je ne conseillerais pas nécessairement d'ajouter une dépendance juste pour cela. Mais dans un projet où vous utilisez déjà cette bibliothèque de toute façon, c'est une solution confortable.

6voto

user136298 Points 1

Voici une version Java 8/streams de la réponse de Louis Wasserman. (Vous pouvez aussi mettre cette méthode directement dans la classe Enum, et enlever un des paramètres)

public boolean isInEnum(String value, Class<E> enumClass) {
    return Arrays.stream(enumClass.getEnumConstants()).anyMatch(e -> e.name().equals(value));
  }

3voto

Paul-59701 Points 159

Je n'ai pas assez de points pour commenter directement la réponse de Simon Tower, mais voici la méthode pour la deuxième façon qu'il a mentionnée qui va directement dans la classe enum elle-même :

 public static boolean isInEnum(String value) {
     return Arrays.stream(EnumClassNameGoesHere.values()).anyMatch(e -> e.name().equals(value));
}

0voto

JoD. Points 188

Évitez d'utiliser une boucle pour effectuer la validation.

Je suggère d'utiliser valueOf . Cette méthode est intégrée aux enums, et peut être envisagée pour une optimisation au moment de la compilation.

Cela reviendrait à mettre en œuvre un système statique Map<String,EnumType> pour optimiser la recherche, une autre considération que vous pouvez prendre.

L'inconvénient est qu'il faudrait utiliser le mécanisme de traitement des exceptions pour attraper une valeur non numérique.

Exemple

public enum DataType {
  //...
  static public boolean has(String value) {
    if (value== null) return false;
    try { 
        // In this implementation - I want to ignore the case
        // if you want otherwise ... remove .toUpperCase()
        return valueOf(value.toUpperCase()); 
    } catch (IllegalArgumentException x) { 
        // the uggly part ...
        return false;
    }
  }
}

Notez également qu'avec l'implémentation du type ci-dessus, votre code est beaucoup plus propre lors de l'appel. Votre main ressemblerait maintenant à quelque chose comme :

public void main(){
    String filter = "SIZE";
    String action = "DELETE";

    // ...

    if (Filter.has(filter) && Action.has(action)) {
      // Appropriate action
    }
}

L'autre option mentionnée consiste à utiliser une carte statique. Vous pouvez utiliser une telle approche pour mettre en cache toute sorte d'indexation basée sur d'autres propriétés également. Dans l'exemple ci-dessous, j'autorise chaque valeur d'enum à avoir une liste de noms d'alias. L'index de recherche dans ce cas sera insensible à la casse, en forçant la majuscule.

public enum Command {
  DELETE("del","rm","remove"),
  COPY("cp"),
  DIR("ls");

  private static final Map<String,Command> ALIAS_MAP = new HashMap<String,Command>();
  static {
    for (Command type:Command.values()) {
      ALIAS_MAP.put(type.getKey().toUpper(),type);
      for (String alias:type.aliases) ALIAS_MAP.put(alias.toUpper(),type);
    }
  }

  static public boolean has(String value) {
    return ALIAS_MAP.containsKey(value.toUpper());
  }

  static public Command fromString(String value) {
    if (value == null) throw new NullPointerException("alias null");
    Command command = ALIAS_MAP.get(value);
    if (command == null) throw new IllegalArgumentException("Not an alias: "+value);
    return command;
  }

  private List<String> aliases;
  private Command(String... aliases) {
    this.aliases = Arrays.asList(aliases);
  }
}

0 votes

Notez les commentaires sur les frais généraux des exceptions. Ils m'ont été cachés lors de ma première publication.

0 votes

Je me suis penché sur un autre sujet similaire. Un utilisateur a mentionné que dans un tel cas, le compilateur JIT optimiserait la surcharge liée à l'exception. La surcharge n'est perceptible que lors du débogage en raison de toute l'instrumentation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X