Java枚举反向查找

时间:2018-07-18 16:50:35

标签: java enums

所以我有这个枚举无法正常工作,需要进行一些修改:

public enum MyEnum {

    CODE000("text description comes here"),

    private final String value;

    private static final Map<String, MyEnum> LOOKUP = Maps.uniqueIndex(
            Arrays.asList(MyEnum.values()),
            MyEnum::getValue
    );

    MyEnum(final String value) {
        this.value = value;
    }

    public String getValue() {
        return value;

    }


    public static MyEnum fromStatus(String status) {
        return LOOKUP.get(status);
    }
}

现在的工作方式是:

MyEnum.fromStatus("text description comes here"),当然我想反过来:

MyEnum.fromStatus("CODE000")返回我"text description comes here"

有人可以建议我如何更改吗?

4 个答案:

答案 0 :(得分:6)

您需要的是文字查找,您可以通过调用itemCount : filtered.length, 来获得:

valueOf

然后:

MyEnum code000 =  MyEnum.valueOf("CODE000");

请注意,如果传递给String val = code000.getValue(); 的字符串不能解析为valueOf中的枚举常量,则会引发异常。

答案 1 :(得分:0)

您的键功能(MyEnum::getValue)错误,因为它返回值。 它必须是MyEnum::name

这将返回枚举,而不是文本描述,因为映射的值为MyEnum类型。您可以通过在枚举上调用getValue来获取文本值,也可以将值存储在映射中而不是枚举

答案 2 :(得分:0)

如果要通过枚举名称获取枚举值,则可以使用以下功能:

public static String fromStatus(String status) {
    MyEnum myEnum = valueOf(status);

    return myEnum.getValue();
}

答案 3 :(得分:0)

到目前为止,答案是使用方法valueOf。只要您提供枚举常量的名称,此方法将返回枚举常量。否则将抛出IllegalArgumentException

在您的问题中,您正在使用查找映射。该地图(看起来像Guava Maps创建的地图)将返回非枚举常量名称null。在这种情况下,它不会抛出IllegalArgumentException。因此,这是一种不同的行为。

此外,您说:“当然,我想反过来”
这意味着您要按状态获取枚举,并按枚举名称获取状态。

因此,您将需要具有两种查找方法:

  • 状态->枚举
  • 名称->状态

但是,如果定义了您提到的两种方法,则会出现编译时错误:

  public static MyEnum fromStatus(String status) { ... }

  public static String fromStatus(String name) { ... }

编译器无法通过名称和参数区分方法。但是,即使您实际上写了MyEnum.fromStatus("CODE000"),它还是您用作参数的枚举常量名称。因此,让我们通过调用第二个方法fromName来解决命名冲突。 MyEnum的代码如下所示:

public enum MyEnum {

  CODE000("text description comes here");

  private final String value;

  private static final Map<String, MyEnum> LOOKUP_ENUM = Maps.uniqueIndex(Arrays.asList(MyEnum.values()), MyEnum::getValue);
  private static final Map<String, String> LOOKUP_STATUS = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::name, MyEnum::getValue));

  MyEnum(final String value) {
    this.value = value;
  }

  public String getValue() {
    return value;

  }

  public static MyEnum fromStatus(String status) {
    return LOOKUP_ENUM.get(status);
  }

  public static String fromName(String name) {
    return LOOKUP_STATUS.get(name);
  }

}

如果要以相同的方式通过名称查找枚举常量(非枚举常量名称也不例外),则需要第三个映射和第三个查找方法:

  private static final Map<String, MyEnum> LOOKUP = Maps.uniqueIndex(Arrays.asList(MyEnum.values()), MyEnum::name);

  public static MyEnum byName(String name) {
    return LOOKUP.get(name);
  }

这将如下工作:

System.out.println(MyEnum.fromStatus("text description comes here")); // CODE000
System.out.println(MyEnum.fromStatus("invalid")); // null - no exception
System.out.println(MyEnum.fromStatus(null)); // null - no exception

System.out.println(MyEnum.fromName("CODE000")); // "text description comes here"
System.out.println(MyEnum.fromName("invalid")); // null - no exception
System.out.println(MyEnum.fromName(null)); // null - no exception

System.out.println(MyEnum.byName("CODE000")); // CODE000
System.out.println(MyEnum.byName("invalid")); // null - no exception
System.out.println(MyEnum.byName(null)); // null - no exception

如果您需要byName方法,我建议将方法fromName重命名为statusByName之类,以使它们易于理解。

最后一个建议:
由于查找方法可能返回null,因此我们可以返回Optional<String> / Optional<MyEnum>作为结果。这样可以立即继续处理结果。

  public static Optional<MyEnum> fromStatus(String status) { ... }
  public static Optional<String> statusByName(String name) { ... }
  public static Optional<MyEnum> byName(String name) { ... }