14

我有两个不同的枚举,我希望能够输出给定的字符串是否是枚举集合的一部分。这是我的代码:

public class Check {
    public enum Filter{SIZE, DATE, NAME};
    public enum Action{COPY, DELETE, REMOVE};

    public boolean isInEnum(String value, Enum e){
        // check if string value is a part of a given enum
        return false;
    }

    public void main(){
        String filter = "SIZE";
        String action = "DELETE";
                // check the strings
        isInEnum(filter, Filter);
        isInEnum(action, Action);
    }
}

eclipse 在最后两行中说“过滤器无法解析为变量”,但除此之外,函数“isInEnum”中的 Enum 参数似乎是错误的。

这里出了点问题,有人可以帮忙吗?

4

6 回答 6

21

最简单(通常也是最有效)的方法如下:

public <E extends Enum<E>> boolean isInEnum(String value, Class<E> enumClass) {
  for (E e : enumClass.getEnumConstants()) {
    if(e.name().equals(value)) { return true; }
  }
  return false;
}

然后你打电话isInEnum(filter, Filter.class)

于 2012-04-17T21:31:34.787 回答
11

如果您不介意使用 Apache commons lang3 库,您可以使用以下代码:

EnumUtils.isValidEnum(Filter.class, filter)

根据文档

此方法与 Enum.valueOf(java.lang.Class, java.lang.String) 的不同之处在于它不会为无效的枚举名称引发异常。

于 2016-03-09T08:03:31.493 回答
6

这是 Louis Wasserman 的答案的 Java 8/streams 版本。(也可以把这个方法直接放到Enum类中,去掉其中一个参数)

public boolean isInEnum(String value, Class<E> enumClass) {
    return Arrays.stream(enumClass.getEnumConstants()).anyMatch(e -> e.name().equals(value));
  }
于 2015-11-10T19:20:26.877 回答
3

我没有足够的分数来直接评论 Simon Tower 的答案,但这里是他提到的第二种方式的方法,它直接在 enum 类本身中进行:

 public static boolean isInEnum(String value) {
     return Arrays.stream(EnumClassNameGoesHere.values()).anyMatch(e -> e.name().equals(value));
}
于 2015-11-17T23:09:33.397 回答
0

避免使用循环进行验证。

我建议使用valueOf. 此方法内置于枚举中,可考虑用于编译时优化。

这类似于实现一个静态Map<String,EnumType>来优化查找,这是您可以考虑的另一个考虑因素。

缺点是您必须使用异常处理机制来捕获非枚举值。

例子

public enum DataType {
  //...
  static public boolean has(String value) {
    if (value== null) return false;
    try { 
        // In this implementation - I want to ignore the case
        // if you want otherwise ... remove .toUpperCase()
        return valueOf(value.toUpperCase()); 
    } catch (IllegalArgumentException x) { 
        // the uggly part ...
        return false;
    }
  }
}

另请注意,通过上述类型实现,您的代码在调用时看起来更清晰。你的主要现在看起来像:

public void main(){
    String filter = "SIZE";
    String action = "DELETE";

    // ...

    if (Filter.has(filter) && Action.has(action)) {
      // Appropriate action
    }
}

然后提到的另一个选项是使用静态地图。您也可以采用这种方法来缓存基于其他属性的所有类型的索引。在下面的示例中,我允许每个枚举值都有一个别名列表。在这种情况下,查找索引将不区分大小写,强制为大写。

public enum Command {
  DELETE("del","rm","remove"),
  COPY("cp"),
  DIR("ls");

  private static final Map<String,Command> ALIAS_MAP = new HashMap<String,Command>();
  static {
    for (Command type:Command.values()) {
      ALIAS_MAP.put(type.getKey().toUpper(),type);
      for (String alias:type.aliases) ALIAS_MAP.put(alias.toUpper(),type);
    }
  }

  static public boolean has(String value) {
    return ALIAS_MAP.containsKey(value.toUpper());
  }

  static public Command fromString(String value) {
    if (value == null) throw new NullPointerException("alias null");
    Command command = ALIAS_MAP.get(value);
    if (command == null) throw new IllegalArgumentException("Not an alias: "+value);
    return command;
  }

  private List<String> aliases;
  private Command(String... aliases) {
    this.aliases = Arrays.asList(aliases);
  }
}
于 2012-09-28T18:52:07.060 回答
0

这也可以按如下方式完成:

public boolean isInEnum(String value, Enum e){
    return Enums.getIfPresent(e.class, value).isPresent();
}

更多细节可以在这里找到。

于 2021-05-04T14:47:44.537 回答