java枚举字符串匹配

java enum string matching

我有一个枚举如下:

public enum ServerTask {

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

我也有一个字符串(比方说字符串 = "Execute"),我想根据它匹配的枚举中的哪个字符串将其变成 ServerTask 枚举的实例。有没有比在我要匹配的字符串和枚举中的每个项目之间进行相等性检查更好的方法呢?似乎这将是很多 if 语句,因为我的枚举相当大

创建静态反向查找图。

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 );
  }

}

在某种程度上,您将不得不遍历您拥有的整个枚举集,并且必须将它们比较为相等 - 通过映射结构(初始人口)或通过基本的循环。

用一个基本的循环相当容易完成,所以我看不出您有任何不想走这条路的理由。下面的代码片段假定该字段名为 friendlyTask.

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

这种方法的注意事项是数据不会存储在内部,并且取决于您实际拥有的枚举数量以及您要调用此方法的次数,它的性能会比使用初始化略差地图.

不过,这种方法是最直接的。如果您发现自己处于拥有数百个枚举的位置(甚至超过 20 个对我来说都是一种气味),请考虑这些枚举代表什么以及应该如何将其分解得更多。

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

如果你只需要这样做一次或两次,用一个 if 语句循环值可能是你最好的选择(比如 Nizil 的评论影射)

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

然而,有一种方法可以完全不迭代这些值。如果你能保证enum实例的名称和它的String值是相同的,那么你可以使用:

ServerTask.valueOf("EXECUTE")

这会给你 ServerTask.EXECUTE。

请参阅 this 答案了解更多信息。

话虽如此,但我不会推荐这种方法,除非您同意让实例具有与其标识符相同的字符串表示形式 并且您的应用程序是性能关键型应用程序,它是大多数情况下 不是 情况。

你可以这样写一个方法:

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的解决方案那样自动。如果枚举发生变化,您将不得不更新开关。