public enum Gender{
m("male"), f("female");
private final String value;
private Gender(String option){
value = option;
}
}
我可以知道如何将字符串“男性”变成任何枚举?是的,该值与枚举不同。这不起作用
Gender.valueOf("male");
我在想提供一个
1)解析for-loop
或
2)静态初始化Map
...
我觉得第二种方式更好,因为当我初始化地图时,如果存在相同的String,我可以抛出运行时异常。
有哪些优点和缺点,还是有其他更好的解决方案?
答案 0 :(得分:4)
我使用地图:
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);
}
}
我认为这比第一种方法有两个优点:
Gender
时间内将字符串转换为O(1)
,而另一种方法则需要O(n)
时间。答案 1 :(得分:2)
这是一个更通用的解决方案。我会在枚举映射到代码值的任何时候使用它。当你有一个枚举表示一系列离散值,例如映射到数据库表时,它会特别有用。请注意,定义的下几个类型只需要编写一次,然后可以在任何枚举上使用。
首先定义一个enum(或要存储在集合中的POJO)将实现的接口:
public interface Coded<T> {
T getCode();
}
以下利用Google Guava,但您可以执行空检查而不是使用Optional类:
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));
}
}
上面的方法使用Class#getEnumConstants来检索枚举中定义的所有值。被调用的实际find方法不仅可以用于枚举,还可以用于数组和集合等。
我们必须定义Predicate以利用Guava's find method:
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());
}
}
该谓词是通用的,因此您可以使用Coded<Integer>
或任何其他具有合理equals()
实现的POJO。
似乎有很多代码,但实际上上面只定义了三种类型,这些类型可以在任意数量的项目中共享。每当你想要搜索一个值时,它就变得微不足道了:
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;
}
}
}
答案 2 :(得分:0)
我经常遇到过这种情况,通常会使用你的第一种方法:
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
}
看到你的value
被宣布为final
并且所有实例都需要从代码中声明,你总是负责值是唯一的,所以对我来说问题几乎不存在。