简体   繁体   English

带有构造函数的Java Enum。 通过构造函数参数获取值的最佳方法

[英]Java Enum with constructor. Best way to get value by constructor argument

Suppose I have the enum below: 假设我有以下枚举:

public enum RockPaperScissors {
    R("Rock"),
    P("Paper"),
    S("Scissors");

    private final String fullName;

    RockPaperScissors(String fullName) {
        this.fullName = fullName;
    }

    public String getFullName() {
        return fullName;
    }

    public static RockPaperScissors getInstanceByFullName(String fullName) {
        return Arrays.stream(values())
                .filter(value -> value.getFullName().equals(fullName))
                .findFirst().orElseThrow(() -> new IllegalArgumentException("No such value in the enum"));
    }
}

I want both RockPaperScissors.valueOf("R") and RockPaperScissors.getInstanceByFullName("Paper") to work because I call them by different data providers. 我想要RockPaperScissors.valueOf("R")RockPaperScissors.getInstanceByFullName("Paper")工作,因为我通过不同的数据提供者调用它们。

Is there any better alternative to the getInstanceByFullName method that I have written? 有没有更好的替代我写的getInstanceByFullName方法?

Edit: My question was whether the Java enum API provides some alternative methods, which apparently it does not. 编辑:我的问题是Java枚举API是否提供了一些替代方法,显然它没有。 As ernest_k suggested, I improved the getInstanceByFullName method. 正如ernest_k建议的那样,我改进了getInstanceByFullName方法。

The simplest solution would probably be to maintain a static Map<String, RockPaperScissors> in the enum: 最简单的解决方案可能是在枚举中维护一个静态Map<String, RockPaperScissors>

public enum RockPaperScissors {
    R ("Rock"),
    P ("Paper"),
    S ("Scissors");

    private static final Map<String, RockPaperScissors> byFullName = new HashMap<>();
    private final String fullName;

    RockPaperScissors(String fullName) {
        this.fullName = fullName;
        byFullName.put(fullName, this);
    }

    public String getFullName() {
        return fullName;
    }

    public static RockPaperScissors getInstanceByFullName(String fullName) {
        return byFullName.get(fullName);
    }
}

Essentially, you just precompute a Map as the enum class is loaded to allow for quick lookups by the full names. 实质上,您只需在加载枚举类时预先计算Map,以允许通过全名快速查找。

(Whether or not it's actually faster than looping over all the values depends on the size of the enum, though. With just three elements, looping might very well be faster.) (但是它实际上是否比循环所有值更快取决于枚举的大小。只有三个元素,循环可能会更快。)

You can do with just one stream operation: 您只需一个流操作即可:

   public static RockPaperScissors getInstanceByFullName(String fullName) {
        return Arrays.stream(values())
              .filter(rockPaperScissors -> rockPaperScissors.getFullName().equals(fullName))
              .findFirst()
              .orElseThrow(() -> new IllegalArgumentException("No such value in the enum"));
    }

You can simplify it and not stream it twice, eg: 您可以简化它,而不是将其stream两次,例如:

public static RockPaperScissors getInstanceByFullName(String fullName) {
    for(RockPaperScissors element : values()) {
        if(element.fullName.equals(fullName)) {
            return element;
        }
    }
    throw new IllegalArgumentException("No such value in the enum");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM