java enum字符串匹配

时间:2015-05-26 16:42:05

标签: java enums

我有一个枚举如下:

public enum ServerTask {

HOOK_BEFORE_ALL_TASKS("Execute"),
COPY_MASTER_AND_SNAPSHOT_TO_HISTORY("Copy master db"),
PROCESS_CHECKIN_QUEUE("Process Check-In Queue"),
...
}

我还有一个字符串(比如string =" Execute")我想根据它与之匹配的枚举中的字符串将其作为ServerTask枚举的实例。有没有比在我想要匹配的字符串和枚举中的每个项目之间进行相等性检查更好的方法呢?因为我的枚举很大,所以看起来这会是很多if语句

4 个答案:

答案 0 :(得分:5)

在某种程度上,你将不得不迭代你拥有的整个枚举集,并且你必须将它们相等 - 通过映射结构(初始填充)或通过一个基本循环。

使用基本循环完成相当容易,所以我没有看到任何你不想走这条路的原因。下面的代码段假设该字段名为friendlyTask

public static ServerTask forTaskName(String friendlyTask) {
    for (ServerTask serverTask : ServerTask.values()) {
        if(serverTask.friendlyTask.equals(friendlyTask)) {
            return serverTask;
        }
    }
    return null;
}

这种方法的警告是数据不会在内部存储,并且根据您实际拥有的枚举数量以及要调用此方法的次数,它的性能会比使用地图初始化时稍差。

然而,这种方法是最直接的。如果你发现自己处于几百个枚举的位置(甚至超过20个是我的气味),请考虑这些枚举所代表的内容以及应该做些什么来突破它。

答案 1 :(得分:1)

创建静态反向查找映射。

public enum ServerTask {

  HOOK_BEFORE_ALL_TASKS("Execute"),
  COPY_MASTER_AND_SNAPSHOT_TO_HISTORY("Copy master db"),
  PROCESS_CHECKIN_QUEUE("Process Check-In Queue"),
  ...
  FINAL_ITEM("Final item");

  // For static data always prefer to use Guava's Immutable library
  // http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html

  static ImmutableMap< String, ServerTask > REVERSE_MAP;

  static
  {
    ImmutableMap.Builder< String, ServerTask > reverseMapBuilder =
      ImmutableMap.builder( );

    // Build the reverse map by iterating all the values of your enum
    for ( ServerTask cur : values() )
    {
       reverseMapBuilder.put( cur.taskName, cur );
    }

    REVERSE_MAP = reverseMapBuilder.build( );
  }

  // Now is the lookup method
  public static ServerTask fromTaskName( String friendlyName ) 
  {
    // Will return ENUM if friendlyName matches what you stored
    // with enum
    return REVERSE_MAP.get( friendlyName );
  }

}

答案 2 :(得分:1)

如果您必须经常从enum 获取String,那么创建像Alexander这样的反向地图可能是值得的。

如果您只需执行一次或两次,则使用单个if语句循环覆盖值可能是您最好的选择(例如Nizil的评论暗示)

for (ServerTask task : ServerTask.values())
{
    //Check here if strings match
}

然而,有一种方法可以根本不迭代这些值。如果您可以确保enum实例的名称及其String值相同,则可以使用:

ServerTask.valueOf("EXECUTE")

将为您提供ServerTask.EXECUTE。

请参阅this答案以获取更多信息。

话虽如此,我不推荐这种方法,除非你能让实例拥有与其标识符相同的字符串表示你的是一个性能至关重要的应用程序,通常是<强>不的情况。

答案 3 :(得分:0)

您可以编写如下方法:

static ServerTask getServerTask(String name)
{
    switch(name)
    {
         case "Execute": return HOOK_BEFORE_ALL_TASKS;
         case "Copy master db": return COPY_MASTER_AND_SNAPSHOT_TO_HISTORY;
         case "Process Check-In Queue": return PROCESS_CHECKIN_QUEUE;
    }
}

它更小,但不像@ Alexander_Pogrebnyak的解决方案那样自动化。如果枚举更改,则必须更新开关。