26

我想根据其字段值获取特定的枚举。

枚举:

public enum CrimeCategory {
    ASBO ("Anti Social Behaviour"),
    BURG ("Burglary"),
    CRIMDAM ("Criminal Damage And Arson"),
    DRUGS ("Drugs"),
    OTHTHEFT ("Other Theft"),
    PUPDISOR ("Public Disorder And Weapons"),
    ROBBERY ("Robbery"),
    SHOPLIF ("Shoplifting"),
    VEHICLE ("Vehicle Crime"),
    VIOLENT ("Violent Crime"),
    OTHER ("Other Crime");

    private  String category;


    private CrimeCategory (String category) {
        this.category = category;
    }

    public String returnString() {
        return category; 
    }
}


获取一个新的枚举:

aStringRecivedFromJson = "Anti Social Behaviour"
CrimeCategory crimeCategoryEnum;
crimeCategoryEnum = CrimeCategory.valueOf(aStringRecivedFromJson); 

我一直在尝试找出一种方法,让上面带回一个枚举,以便它可以HashMap与其他Crime信息一起存储在一个中传递。

预期结果:ASBO

4

4 回答 4

37

作为参考,这里有一个 HashMap 的替代解决方案:

enum CrimeCategory {
  ASBO("Anti Social Behaviour"),
  BURG("Burglary"),
  CRIMDAM("Criminal Damage And Arson"),
  DRUGS("Drugs"),
  OTHTHEFT("Other Theft"),
  PUPDISOR("Public Disorder And Weapons"),
  ROBBERY("Robbery"),
  SHOPLIF("Shoplifting"),
  VEHICLE("Vehicle Crime"),
  VIOLENT("Violent Crime"),
  OTHER("Other Crime");

  private static final Map<String, CrimeCategory> map = new HashMap<>(values().length, 1);

  static {
    for (CrimeCategory c : values()) map.put(c.category, c);
  }

  private final String category;

  private CrimeCategory(String category) {
    this.category = category;
  }

  public static CrimeCategory of(String name) {
    CrimeCategory result = map.get(name);
    if (result == null) {
      throw new IllegalArgumentException("Invalid category name: " + name);
    }
    return result;
  }
}
于 2013-03-12T20:45:31.950 回答
26

CrimeCategory枚举添加静态方法:

public static CrimeCategory valueOf(String name) {
    for (CrimeCategory category : values()) {
        if (category.category.equals(name)) {
            return category;
        }
    }    
    throw new IllegalArgumentException(name);
}
于 2013-03-12T19:29:54.647 回答
4

基于实例字段的值返回枚举常量的静态工厂方法采用其他答案中描述的两种形式之一:基于迭代枚举值的解决方案,或基于HashMap.

对于常量数量较少的枚举,迭代解决方案应该与HashMap解决方案一样高效(这需要计算哈希码,将其与存储桶匹配,并假设不会发生哈希冲突)。

对于较大的枚举,基于映射的解决方案将具有更高的性能(但需要内存中的存储空间)。但是,如果不经常调用工厂方法,那么使用映射对整体性能的提升可能仍然非常小。

对静态工厂方法使用迭代查找或基于映射的查找的总体决定最终将取决于您的要求和环境。从迭代查找开始,然后在分析显示实际性能问题时更改为基于映射的实现永远不会错。

最后,从 Java 8 开始,StreamsAPI 支持基于管道的映射解决方案(其性能应该类似于迭代解决方案)。例如,假设您想创建一个接口,您可以在任何枚举类上使用该接口来表达您的意图,即它应该可以通过它的实例字段之一进行匹配。我们称之为接口Matchable。该接口定义了一个方法,该方法返回您要匹配的实例字段(例如。getField())。这个接口还可以定义一个静态工厂方法来从任何实现的枚举类返回一个常量:

interface Matchable {

    Object getField();

    public static <E extends Enum<E> & Matchable> E forToken(Class<E> cls, Object token) {

        return Stream.of(cls.getEnumConstants())
            .filter(e -> e.getField().equals(token))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unknown token '" +
                    token + "' for enum " + cls.getName()));
    }
}

现在,您定义的任何实现的枚举类都Matchable可以使用Matchable.forToken()静态工厂方法来查找其实例字段值与提供的参数匹配的枚举常量。

泛型类型声明E extends Enum<E> & Matchable确保作为参数传递给方法的类型标记将用于实现的枚举类Matchable(否则代码将无法编译)。

于 2016-10-12T18:20:42.147 回答
1

Assylias的回答很棒。虽然我会Optional从工厂方法返回一个让客户端处理找不到枚举的情况(当然,IllegalArgumentException如果你在内部使用这个枚举并且你认为用错误的参数调用这个方法永远不会发生,那么抛出可能会更好 -这是你的选择)。

而且我会将它包装Map成不可修改的包装器,以免在您的枚举中意外修改它(这Map是私有的,但有人可以稍后在添加新功能时对其进行修改 - 它至少会强制考虑它):

enum CrimeCategory {
    ASBO("Anti Social Behaviour"),
    BURG("Burglary"),
    CRIMDAM("Criminal Damage And Arson"),
    DRUGS("Drugs"),
    OTHTHEFT("Other Theft"),
    PUPDISOR("Public Disorder And Weapons"),
    ROBBERY("Robbery"),
    SHOPLIF("Shoplifting"),
    VEHICLE("Vehicle Crime"),
    VIOLENT("Violent Crime"),
    OTHER("Other Crime");

    private static final Map<String, CrimeCategory> MAP;

    static {
         Map<String, CrimeCategory> crimeCategoryMap = Arrays.stream(values())
                .collect(toMap(cg -> cg.category, e -> e));
         MAP = Collections.unmodifiableMap(crimeCategoryMap);
    }

    private final String category;

    private CrimeCategory(String category) {
        this.category = category;
    }

    public static Optional<CrimeCategory> of(final String name) {
        return Optional.ofNullable(MAP.get(name));
    }
}
于 2019-11-23T14:00:30.457 回答