Java 枚举:将字符串转换为枚举

Java 枚举:将字符串转换为枚举,java,enums,Java,Enums,我可以知道如何将字符串“male”转换为任何枚举吗?是,该值与枚举不同。这行不通 public enum Gender{ m("male"), f("female"); private final String value; private Gender(String option){ value = option; } } 我在考虑提供一个 1) 使用for循环进行解析 或 2) 静态初始化映射 我觉得第二种方法更好,因为当我初始化

我可以知道如何将字符串“male”转换为任何枚举吗?是,该值与枚举不同。这行不通

public enum Gender{

    m("male"), f("female");

    private final String value;

    private Gender(String option){
          value = option;
    }
}
我在考虑提供一个

1) 使用for循环进行解析

2) 静态初始化映射

我觉得第二种方法更好,因为当我初始化映射时,如果存在相同的字符串,我可以抛出运行时异常

优点和缺点是什么?或者还有其他更好的解决方案吗?

我会使用地图:

 Gender.valueOf("male"); 
公共枚举性别{
男(“男”),女(“女”);
私有最终字符串值;
私有静态最终映射值=新HashMap();
静止的{
for(Gender g:Gender.values()){
if(value.put(g.value,g)!=null){
抛出新的IllegalArgumentException(“重复值:+g.value”);
}
}
}
私人性别(字符串选项){
价值=期权;
}
公共静态性别fromString(字符串选项){
返回值.get(选项);
}
}
我认为这比第一种方法有两个优点:

public enum Gender {

    m("male"), f("female");

    private final String value;

    private static final Map<String, Gender> values = new HashMap<String, Gender>();
    static {
        for (Gender g : Gender.values()) {
            if (values.put(g.value, g) != null) {
                  throw new IllegalArgumentException("duplicate value: " + g.value);
            }
        }
    }

    private Gender(String option) {
          value = option;
    }

    public static Gender fromString(String option) {
        return values.get(option);
    }
}
  • 此方法可以在
    O(1)
    time中将字符串转换为
    Gender
    ,而另一种方法需要
    O(n)
    time
  • 这将自动检测重复值

  • 我曾多次遇到这种情况,通常使用您的第一种方法:

    public enum Gender {
    
        m("male"), f("female");
    
        private final String value;
    
        private static final Map<String, Gender> values = new HashMap<String, Gender>();
        static {
            for (Gender g : Gender.values()) {
                if (values.put(g.value, g) != null) {
                      throw new IllegalArgumentException("duplicate value: " + g.value);
                }
            }
        }
    
        private Gender(String option) {
              value = option;
        }
    
        public static Gender fromString(String option) {
            return values.get(option);
        }
    }
    

    由于您的
    是声明的
    final
    ,并且所有实例都需要从代码中声明,因此您始终要对值的唯一性负责,因此对我来说,这个问题几乎不存在。

    这是一个更普遍的解决方案。每当枚举映射到代码值时,我都会使用它。当一个枚举表示一系列离散值(例如映射到数据库表)时,它特别有用。请注意,接下来定义的几个类型只需编写一次,然后就可以在任何枚举上使用

    首先定义枚举(或存储在集合中的POJO)将实现的接口:

    public static Gender forValue(String value) {
        for (Gender gender : gender.values()) {
            if (gender.value.equals(value)) {
                return gender;
            }
        }
    
        return null; // or throw something like IllegalArgumentException 
    }
    

    使用第二个选项更好,而且会被多次使用。为什么不使用Gender.valueOf(“m”)?因为这些值是在运行时初始化的。。m(常数.male())@NarendraPathai有什么例子吗?还是定义模式?我也这么觉得,只是想确认一下。嘿嘿哇,真不错!它看起来有点过度设计,但调用方的代码非常简单。无论如何,您还应该利用guava缓存,使其在O(1)而不是O(n)中运行
    public final class CodedFinder {
    
        private CodedFinder() {}
    
        public static <V, T extends Enum<T> & Coded<V>> T find(final Class<T> target, final V code) {
            final Optional<T> found = findInternal(Arrays.asList(target.getEnumConstants()), code);
            if (! found.isPresent()) {
                throw new IllegalArgumentException(code.toString() + " is invalid for " + target.getSimpleName());
            }
            return found.get();
        }
    
        // Additional find methods for arrays and iterables redacted for clarity.
    
        private static <V, T extends Coded<V>> Optional<T> findInternal(final Iterable<T> values, final V code) {
            return Iterables.tryFind(values, CodedPredicate.of(code));
        }
    }
    
    public final class CodedPredicate<V, T extends Coded<V>> implements com.google.common.base.Predicate<T> {
        private final V value;
    
        private CodedPredicate(final V value) {
            this.value = value;
        }
    
        public static <V, T extends Coded<V>> CodedPredicate<V, T> of(final V value) {
            return new CodedPredicate<V, T>(value);
        }
    
        public boolean apply(final T current) {
            return value.equals(current.getCode());
        }
    }
    
    public final class GenderTest {
    
        @Test(groups="unit")
        public static void testValid() {
    
            assert CodedFinder.find(Gender.class, "male")  == Gender.m;
            assert CodedFinder.find(Gender.class, "female") == Gender.f;
        }
    
        @Test(groups="unit", expectedExceptions=IllegalArgumentException.class)
        public static void testInvalid() {
    
            CodedFinder.find(Gender.class, "foo");
        }
    
        public enum Gender implements Coded<String> {
    
            m("male"), f("female");
    
            private final String value;
    
            private Gender(final String option) {
                  value = option;
            }
    
            public String getCode()
            {
                return value;
            }
        }
    }