Как проверить, является ли данная строка частью любого заданного Enum в Java?

У меня есть два разных перечисления, и я хочу иметь возможность выводить, string является частью коллекции enum. это мой код:

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 говорит, что в последних двух строках "Фильтр не может быть разрешен переменной", но кроме того, кажется, что параметр Enum в функции isInEnum неверен.

Что-то очень плохое здесь может кто-нибудь помочь?

Ответ 1

Самый простой (и обычно наиболее эффективный) способ заключается в следующем:

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;
}

а затем вы вызываете isInEnum(filter, Filter.class).

Ответ 2

Если вы не против использования библиотеки Apache commons lang3, вы можете использовать следующий код:

EnumUtils.isValidEnum(Filter.class, filter)

В соответствии с docs:

Этот метод отличается от Enum.valueOf(java.lang.Class, java.lang.String) тем, что он не генерирует исключение для недопустимого имени перечисления.

Ответ 3

Вот версия ответа на Java 8/streams Луи Вассермана. (Вы также можете поместить этот метод непосредственно в класс Enum и удалить один из параметров)

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

Ответ 4

У меня недостаточно очков, чтобы прокомментировать ответ Саймона Батона напрямую, но вот метод второго способа, о котором он упомянул, идет непосредственно в класс перечисления:

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

Ответ 5

Избегайте использования цикла для проверки.

Я бы предложил использовать valueOf. Этот метод встроен в перечисления и может быть рассмотрен для оптимизации времени компиляции.

Это будет похоже на реализацию статического Map<String,EnumType>, чтобы оптимизировать поиск, и другое соображение, которое вы можете предпринять.

Недостатком является то, что вам нужно будет использовать механизм обработки исключений, чтобы поймать значение без перечисления.

Пример

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;
    }
  }
}

Также обратите внимание, что при реализации типа выше ваш код выглядит намного чище при вызове. Теперь ваш главный выглядит примерно так:

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

    // ...

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

Тогда другой упомянутый параметр - использовать статическую карту. Вы можете использовать такой подход для кэширования всех видов индексирования на основе других свойств. В приведенном ниже примере я разрешаю каждому значению перечисления иметь список псевдонимов. Индекс поиска в этом случае будет нечувствительным к регистру, заставляя заглавные буквы.

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);
  }
}