Java: Проверьте, содержит ли перечисление заданную строку?

Здесь моя проблема - я ищу (если он вообще существует) перечислимый эквивалент ArrayList.contains(); ,

Вот пример моей проблемы с кодом:

enum choices {a1, a2, b1, b2};

if(choices.???(a1)}{
//do this
} 

Теперь я понимаю, что ArrayList of Strings будет лучшим маршрутом здесь, но мне нужно пропустить содержимое моего enum через switch/case в другом месте. Отсюда и моя проблема.

Если предположить, что чего-то подобного не существует, как я могу это сделать?

Ответ 1

Это должно сделать это:

public static boolean contains(String test) {

    for (Choice c : Choice.values()) {
        if (c.name().equals(test)) {
            return true;
        }
    }

    return false;
}

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

Изменить: Если перечисление очень велико, вы можете вставлять значения в HashSet:

public static HashSet<String> getEnums() {

  HashSet<String> values = new HashSet<String>();

  for (Choice c : Choice.values()) {
      values.add(c.name());
  }

  return values;
}

Тогда вы можете просто сделать: values.contains("your string"), который возвращает true или false.

Ответ 2

Используйте Apache commons lang3 lib вместо

 EnumUtils.isValidEnum(MyEnum.class, myValue)

Ответ 3

Вы можете использовать Enum.valueOf()

enum Choices{A1, A2, B1, B2};

public class MainClass {
  public static void main(String args[]) {
    Choices day;

    try {
       day = Choices.valueOf("A1");
       //yes
    } catch (IllegalArgumentException ex) {  
        //nope
  }
}

Если вы ожидаете, что проверка будет часто терпеть неудачу, вам может быть лучше использовать простой цикл, как показали другие - если ваши перечисления содержат много значений, возможно, builda HashSet или аналогичный из ваших перечислимых значений, преобразованных в строку, и запросите вместо этого HashSet.

Ответ 4

Если вы используете Java 1.8, вы можете выбрать Stream + Lambda для реализации этого:

public enum Period {
    DAILY, WEEKLY
};

//This is recommended
Arrays.stream(Period.values()).anyMatch((t) -> t.name().equals("DAILY1"));
//May throw java.lang.IllegalArgumentException
Arrays.stream(Period.values()).anyMatch(Period.valueOf("DAILY")::equals);

Ответ 5

Guavas Enums может быть вашим другом

Как, например, это:

enum MyData {
    ONE,
    TWO
}

@Test
public void test() {

    if (!Enums.getIfPresent(MyData.class, "THREE").isPresent()) {
        System.out.println("THREE is not here");
    }
}

Ответ 6

Еще лучше:

enum choices {
   a1, a2, b1, b2;

  public static boolean contains(String s)
  {
      for(choices choice:values())
           if (choice.name().equals(s)) 
              return true;
      return false;
  } 

};

Ответ 7

Вы можете сначала преобразовать перечисление в список, а затем использовать список содержит метод

enum Choices{A1, A2, B1, B2};

List choices = Arrays.asList(Choices.values());

//compare with enum value 
if(choices.contains(Choices.A1)){
   //do something
}

//compare with String value
if(choices.contains(Choices.valueOf("A1"))){
   //do something
}

Ответ 8

Вы можете использовать этот

YourEnum {A1, A2, B1, B2}

boolean contains(String str){ 
    return Sets.newHashSet(YourEnum.values()).contains(str);
}                                  

Обновление, предлагаемое @wightwulf1944, включено, чтобы сделать решение более эффективным.

Ответ 9

Здесь было упомянуто несколько библиотек, но я скучаю по той, которую я действительно искал: Spring!

Существует ObjectUtils # содержитConstant, который по умолчанию не учитывает регистр, но может быть строгим, если хотите. Используется так:

if(ObjectUtils.containsConstant(Choices.values(), "SOME_CHOISE", true)){
// do stuff
}

Примечание. Я использовал перегруженный метод, чтобы продемонстрировать, как использовать проверку с учетом регистра. Вы можете опустить логическое значение, чтобы поведение не чувствительно к регистру.

Будьте осторожны с большими перечислениями, поскольку они не используют реализацию Map, как это делают некоторые...

В качестве бонуса он также предоставляет вариант valueOf: ObjectUtils # caseInsensitiveValueOf без учета регистра

Ответ 10

Несколько предположений:
1) Нет попытки/улова, так как это исключительный контроль потока
2) метод "содержит" должен быть быстрым, поскольку он обычно выполняется несколько раз.
3) Пространство не ограничено (обычное для обычных решений)

import java.util.HashSet;
import java.util.Set;

enum Choices {
    a1, a2, b1, b2;

    private static Set<String> _values = new HashSet<>();

    // O(n) - runs once
    static{
        for (Choices choice : Choices.values()) {
            _values.add(choice.name());
        }
    }

    // O(1) - runs several times
    public static boolean contains(String value){
        return _values.contains(value);
    }
}

Ответ 11

Я не думаю, что есть, но вы можете сделать что-то вроде этого:

enum choices {a1, a2, b1, b2};

public static boolean exists(choices choice) {
   for(choice aChoice : choices.values()) {
      if(aChoice == choice) {
         return true;
      }
   }
   return false;
}

Edit:

Посмотрите на версию Ричарда, так как это более подходит, так как это не сработает, если вы не конвертируете его в Strings, что делает Ричардс.

Ответ 12

Почему бы не комбинировать ответ Pablo с valueOf()?

public enum Choices
{
    a1, a2, b1, b2;

    public static boolean contains(String s) {
        try {
            Choices.valueOf(s);
            return true;
        } catch (Exception e) {
            return false;
        }
}

Ответ 13

Если вы используете Apache Commons (или хотите сделать это), вы можете проверить его с помощью:

ArrayUtils.contains(choices.values(), value)

Ответ 14

Этот работает для меня:

Arrays.asList(YourEnum.values()).toString().contains("valueToCheck");

Ответ 15

Этот подход можно использовать для проверки любого Enum, вы можете добавить его в класс Utils:

public static <T extends Enum<T>> boolean enumContains(Class<T> enumerator, String value)
{
    for (T c : enumerator.getEnumConstants()) {
        if (c.name().equals(value)) {
            return true;
        }
    }
    return false;
}

Используйте его следующим образом:

boolean isContained = Utils.enumContains(choices.class, "value");

Ответ 16

Я создал следующий класс для этой проверки

public class EnumUtils {

    public static boolean isPresent(Enum enumArray[], String name) {
        for (Enum element: enumArray ) {
            if(element.toString().equals(name))
                return true;
        }
        return false;
    }

}

пример использования:

public ArrivalEnum findArrivalEnum(String name) {

    if (!EnumUtils.isPresent(ArrivalEnum.values(), name))
        throw new EnumConstantNotPresentException(ArrivalEnum.class,"Arrival value must be 'FROM_AIRPORT' or 'TO_AIRPORT' ");

    return ArrivalEnum.valueOf(name);
}

Ответ 17

Вы можете использовать valueOf("a1"), если хотите посмотреть на String

Ответ 18

Это перечисление, это постоянные значения, поэтому, если в выражении switch он просто делает что-то вроде этого:

case: val1
case: val2

Также почему вам нужно знать, что объявлено как константа?

Ответ 19

С guava это еще проще:

boolean isPartOfMyEnum(String myString){

return Lists.newArrayList(MyEnum.values().toString()).contains(myString);

}

Ответ 20

Это объединяет все подходы из предыдущих методов и должно иметь эквивалентную производительность. Он может использоваться для любого перечисления, встраивает решение "Изменить" из @Richard H и использует Исключения для недопустимых значений, таких как @bestsss. Единственный компромисс заключается в том, что класс должен быть указан, но это превращает его в двухстрочный.

import java.util.EnumSet;

public class HelloWorld {

static enum Choices {a1, a2, b1, b2}

public static <E extends Enum<E>> boolean contains(Class<E> _enumClass, String value) {
    try {
        return EnumSet.allOf(_enumClass).contains(Enum.valueOf(_enumClass, value));    
    } catch (Exception e) {
        return false; 
    }
}

public static void main(String[] args) {
    for (String value : new String[] {"a1", "a3", null}) {
        System.out.println(contains(Choices.class, value));
    }
}

}

Ответ 21

com.google.common.collect.Sets.newHashSet(MyEnum.values()).contains("myValue")

Ответ 22

чтобы проверить, присутствует ли значение, а также получить значение перечисления в обратном порядке:

protected TradeType getEnumType(String tradeType) {
    if (tradeType != null) {
        if (EnumUtils.isValidEnum(TradeType.class, tradeType)) {
            return TradeType.valueOf(tradeType);
        }
    }
    return null;
}

Ответ 23

Если вы используете Java 8 или выше, вы можете сделать это:

boolean isPresent(String testString){
      return Stream.of(Choices.values()).map(Enum::name).collect(Collectors.toSet()).contains(testString);
}

Ответ 24

  Set.of(CustomType.values())
     .contains(customTypevalue) 

Ответ 25

public boolean contains(Choices value) {
   return EnumSet.allOf(Choices.class).contains(value);
}

Ответ 26

Моя репутация меньше, чем требуется, чтобы комментировать, но я думаю, что ответы chaiyachaiya и Pablo Santa Cruz полностью ошибочны. Во-первых, Enum перезаписывает hashcode с помощью оператора ==, так как экземпляры гарантированно являются одноточечными и поэтому не сравнивают логическое равенство операндов. Поэтому, если мы используем MyEnum.values() и проверяем с помощью contains(), мы всегда получаем false. Во-вторых, MyEnum.values().toString() вызывает toString() в объекте класса MyEnum, а не в экземплярах класса MyEnum (если вы переопределите этот метод в классе причин). Итак, что вы получите с помощью Lists.newArrayList(MyEnum.values().toString()).contains(myString)?

Ответ 27

enum довольно мощные в Java. Вы легко можете добавить метод contains к вашему перечислению (так как вы добавите метод в класс):

enum choices {
  a1, a2, b1, b2;

  public boolean contains(String s)
  {
      if (s.equals("a1") || s.equals("a2") || s.equals("b1") || s.equals("b2")) 
         return true;
      return false;
  } 

};