Как проверить, является ли данная строка частью любого заданного 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);
}
}