[英]Case-insensitive matching of a string to a Java enum
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);
并且它将为任何enum
完全实现Day.lookup()
方法的功能,而无需为每个enum
重新编写相同的方法。
我发现获得泛型的特殊混合有点棘手,但这是有效的。
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"));
}
我认为最简单安全的方法是:
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);
从版本3.8开始,apache commons-lang EnumUtils有两个方便的方法:
getEnumIgnoreCase(final Class<E> enumClass, final String enumName)
isValidEnumIgnoreCase(final Class<E> enumClass, final String enumName)
一个通用的解决方案是遵守常量大写的约定。 (或者在您的特定情况下使用查找字符串的大写)。
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");
对于 Android 和相对较短的 Enum,我执行简单循环并比较名称忽略大小写。
public enum TransactionStatuses {
public static TransactionStatuses from(String name) {
for (TransactionStatuses status : TransactionStatuses.values()) {
if (status.name().equalsIgnoreCase(name)) {
return status;
}
}
return null;
}
}
您可以使用Class
的getEnumConstants()
方法,如果Class
表示枚举,则返回所有枚举类型的数组,否则返回null
。
如果此 Class 对象不表示枚举类型,则返回此枚举类的元素或 null。
您增强的 for 循环行将如下所示:
for (T d : enumType.getEnumConstants()) {
我还没有测试过这个,但为什么不像这个SO 答案中提到的那样重载这些方法
public enum Regular { NONE, HOURLY, DAILY, WEEKLY; public String getName() { return this.name().toLowerCase(); } }
并且它将为任何枚举完全实现 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() 方法一样,那将会很好,但我认为没有办法做到这一点。
我使用这种方式将字符串不区分大小写匹配到 java 枚举Day[] days = Day.values(); for(Day day: days) { System.out.println("MONDAY".equalsIgnoreCase(day.name())); }
Day[] days = Day.values(); for(Day day: days) { System.out.println("MONDAY".equalsIgnoreCase(day.name())); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.