Подтвердить что ты не робот

Нечувствительное к регистру сопоставление строки с перечислением Java

Java предоставляет метод valueOf() для каждого объекта Enum<T>, поэтому заданный enum как

public enum Day {
  Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}

можно выполнить поиск, например

Day day = Day.valueOf("Monday");

Если строка, переданная в valueOf(), не соответствует (чувствительна к регистру) существующему значению Day, генерируется IllegalArgumentException.

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

public static Day lookup(String day) {
  for (Day d : Day.values()) {
    if (d.name().equalsIgnoreCase(day)) {
      return type;
    }
  }
  return null;
}

Существует ли какой-либо общий способ, не используя кеширование значений или любых других дополнительных объектов, написать статический метод lookup(), как указано выше, только один раз (т.е. не для каждого enum), учитывая, что values() метод неявно добавляется в класс Enum<E> во время компиляции?

Подпись такого "общего" lookup() метода будет аналогична методу Enum.valueOf(), то есть:

public static <T extends Enum<T>> T lookup(Class<T> enumType, String name);

и он будет точно реализовывать функциональность метода Day.lookup() для любого enum, без необходимости переписывать один и тот же метод для каждого enum.

4b9b3361

Ответ 1

Я нашел сложную смесь дженериков немного сложной, но это работает.

public static <T extends Enum<?>> T searchEnum(Class<T> enumeration,
        String search) {
    for (T each : enumeration.getEnumConstants()) {
        if (each.name().compareToIgnoreCase(search) == 0) {
            return each;
        }
    }
    return null;
}

Пример

public enum Horse {
    THREE_LEG_JOE, GLUE_FACTORY
};

public static void main(String[] args) {
    System.out.println(searchEnum(Horse.class, "Three_Leg_Joe"));
    System.out.println(searchEnum(Day.class, "ThUrSdAy"));
}

Ответ 2

Я бы подумал, что самым простым безопасным способом это будет:

Arrays.stream(Day.values())
    .filter(e -> e.name().equalsIgnoreCase(dayName)).findAny().orElse(null);

Ответ 3

Для Android и относительно коротких Enums я делаю простой цикл и сравниваю имя, игнорируя случай.

public enum TransactionStatuses {
    public static TransactionStatuses from(String name) {
        for (TransactionStatuses status : TransactionStatuses.values()) {
            if (status.name().equalsIgnoreCase(name)) {
                return status;
            }
        }
        return null;
    }
}

Ответ 4

Общее решение будет заключаться в том, что keeo означает, что константы имеют верхний регистр. (Или в вашем конкретном случае используйте заглавные буквы в строке поиска).

public static <E extends Enum<E>> E lookup(Class<E> enumClass,
        String value) {
    String canonicalValue.toUpperCase().replace(' ', '_');
    return Enum<E>.valueOf(enumClass, canonicalValue);
}

enum Day(MONDAY, ...);
Day d = lookup(Day,class, "thursday");

Ответ 5

Вы можете использовать Class getEnumConstants() method, который возвращает массив всех типов перечисления, если Class представляет enum или null, если нет.

Возвращает элементы этого класса enum или null, если этот объект класса не представляет тип перечисления.

Ваша расширенная строка цикла будет выглядеть так:

for (T d : enumType.getEnumConstants()) {

Ответ 6

и он будет точно реализовывать функции Day.lookup() метод для любого перечисления, без необходимости переписывать тот же метод для каждое перечисление.

Вероятно, вы можете написать класс утилиты для выполнения этого как следующего.

public class EnumUtil {

    private EnumUtil(){
        //A utility class
    }

    public static <T extends Enum<?>> T lookup(Class<T> enumType,
                                                   String name) {
        for (T enumn : enumType.getEnumConstants()) {
            if (enumn.name().equalsIgnoreCase(name)) {
                return enumn;
            }
        }
        return null;
    }

    // Just for testing
    public static void main(String[] args) {
        System.out.println(EnumUtil.lookup(Day.class, "friday"));
        System.out.println(EnumUtil.lookup(Day.class, "FrIdAy"));
    }

}

enum Day {
    Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}

Было бы неплохо, если бы в Java был способ расширить класс Enum, неявно добавляя методы, как только метод values ​​() добавляется, но я не думаю, что есть способ сделать это.