字符串与Java枚举的不区分大小写匹配

时间:2015-02-04 22:39:52

标签: java generics enums

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重写相同的方法。

9 个答案:

答案 0 :(得分:36)

我发现特殊混合的泛型有点棘手,但这很有效。

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

答案 1 :(得分:27)

我认为最简单的安全方法是:

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

或者如果你想使用类对象,那么:

Arrays.stream(enumClass.getEnumConstants())
    .filter(e -> (Enum)e.name().equalsIgnoreCase(dayName)).findAny().orElse(null);

答案 2 :(得分:6)

从版本 3.8开始 apache commons-lang EnumUtils有两种方便的方法:

  • getEnumIgnoreCase(final Class<E> enumClass, final String enumName)
  • isValidEnumIgnoreCase(final Class<E> enumClass, final String enumName)

答案 3 :(得分:5)

对于Android和相对较短的枚举,我执行简单的循环并比较忽略大小写的名称。

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

答案 4 :(得分:4)

如果Class表示枚举,则可以使用Class's getEnumConstants() method返回所有枚举类型的数组,如果不是null,则可以使用for (T d : enumType.getEnumConstants()) {

  

返回此枚举类的元素,如果此Class对象不表示枚举类型,则返回null。

你的增强型for循环线看起来像这样:

{{1}}

答案 5 :(得分:4)

通用的解决方案是遵守常量为大写的约定。 (或者在您的特定情况下使用查找字符串)。

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

答案 6 :(得分:1)

  

它将完全实现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()方法一样,但我不认为有办法做到这一点

答案 7 :(得分:0)

我正在使用这种方式将字符串与Java枚举进行不区分大小写的匹配 Server >> Settings >> Features >> "Login Cookie Validity" a

答案 8 :(得分:0)

我还没有测试过,但是为什么不重载SO answer中提到的这些方法

public enum Regular {
    NONE,
    HOURLY,
    DAILY,
    WEEKLY;

    public String getName() {
        return this.name().toLowerCase();
    }    
}