Java: Проверить, содержит ли enum заданную строку? - PullRequest
134 голосов
/ 08 февраля 2011

Вот моя проблема - я ищу (если он вообще существует) эквивалент перечисления ArrayList.contains();.

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

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

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

СейчасЯ понимаю, что ArrayList из Strings будет лучшим маршрутом здесь, но мне нужно пропустить содержимое моего перечисления через переключатель / регистр в другом месте.Отсюда моя проблема.

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

Ответы [ 26 ]

194 голосов
/ 12 февраля 2014

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

 EnumUtils.isValidEnum(MyEnum.class, myValue)
169 голосов
/ 08 февраля 2011

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

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.

45 голосов
/ 08 февраля 2011

Вы можете использовать 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.

26 голосов
/ 03 июня 2016

Если вы используете 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);
18 голосов
/ 26 октября 2015

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

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

enum MyData {
    ONE,
    TWO
}

@Test
public void test() {

    if (!Enums.getIfPresent(MyData.class, "THREE").isPresent()) {
        System.out.println("THREE is not here");
    }
}
16 голосов
/ 14 февраля 2012

Еще лучше:

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

};
9 голосов
/ 23 февраля 2017

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

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
}
7 голосов
/ 07 октября 2015

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

YourEnum {A1, A2, B1, B2}

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

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

7 голосов
/ 15 декабря 2017

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

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

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

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

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

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

6 голосов
/ 15 мая 2016

Несколько предположений:
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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...