如何从 String 值中查找 Java 枚举?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1080904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I lookup a Java enum from its String value?
提问by peter.murray.rust
I would like to lookup an enum from its string value (or possibly any other value). I've tried the following code but it doesn't allow static in initialisers. Is there a simple way?
我想从其字符串值(或可能的任何其他值)中查找枚举。我已经尝试了以下代码,但它不允许在初始化程序中使用静态。有没有简单的方法?
public enum Verbosity {
BRIEF, NORMAL, FULL;
private static Map<String, Verbosity> stringMap = new HashMap<String, Verbosity>();
private Verbosity() {
stringMap.put(this.toString(), this);
}
public static Verbosity getVerbosity(String key) {
return stringMap.get(key);
}
};
采纳答案by Gareth Davis
Use the valueOf
method which is automatically created for each Enum.
使用valueOf
为每个 Enum 自动创建的方法。
Verbosity.valueOf("BRIEF") == Verbosity.BRIEF
For arbitrary values start with:
对于任意值,开头为:
public static Verbosity findByAbbr(String abbr){
for(Verbosity v : values()){
if( v.abbr().equals(abbr)){
return v;
}
}
return null;
}
Only move on later to Map implementation if your profiler tells you to.
如果您的分析器告诉您,请稍后再转到 Map 实现。
I know it's iterating over all the values, but with only 3 enum values it's hardly worth any other effort, in fact unless you have a lot of values I wouldn't bother with a Map it'll be fast enough.
我知道它正在迭代所有的值,但只有 3 个枚举值几乎不值得做任何其他努力,事实上,除非你有很多值,否则我不会打扰 Map 它会足够快。
回答by Fredrik
回答by Lyle
You're close. For arbitrary values, try something like the following:
你很接近。对于任意值,请尝试以下操作:
public enum Day {
MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;
private final String abbreviation;
// Reverse-lookup map for getting a day from an abbreviation
private static final Map<String, Day> lookup = new HashMap<String, Day>();
static {
for (Day d : Day.values()) {
lookup.put(d.getAbbreviation(), d);
}
}
private Day(String abbreviation) {
this.abbreviation = abbreviation;
}
public String getAbbreviation() {
return abbreviation;
}
public static Day get(String abbreviation) {
return lookup.get(abbreviation);
}
}
回答by Adam Gent
@Lyle's answer is rather dangerous and I have seen it not work particularly if you make the enum a static inner class. Instead I have used something like this which will load the BootstrapSingleton maps before the enums.
@Lyle 的回答相当危险,我发现如果您将枚举设置为静态内部类,它就不起作用。相反,我使用了这样的东西,它将在枚举之前加载 BootstrapSingleton 映射。
Editthis should not be a problem any more with modern JVMs (JVM 1.6 or greater) but I do think there are still issues with JRebel but I haven't had a chance to retest it.
使用现代 JVM(JVM 1.6 或更高版本)编辑这应该不再是问题,但我确实认为 JRebel 仍然存在问题,但我还没有机会重新测试它。
Load me first:
先加载我:
public final class BootstrapSingleton {
// Reverse-lookup map for getting a day from an abbreviation
public static final Map<String, Day> lookup = new HashMap<String, Day>();
}
Now load it in the enum constructor:
现在在枚举构造函数中加载它:
public enum Day {
MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;
private final String abbreviation;
private Day(String abbreviation) {
this.abbreviation = abbreviation;
BootstrapSingleton.lookup.put(abbreviation, this);
}
public String getAbbreviation() {
return abbreviation;
}
public static Day get(String abbreviation) {
return lookup.get(abbreviation);
}
}
If you have an inner enum you can just define the Map above the enum definition and that (in theory) should get loaded before.
如果你有一个内部枚举,你可以在枚举定义上方定义 Map 并且(理论上)应该在之前加载。
回答by Midhun
Perhaps, take a look at this. Its working for me.
The purpose of this is to lookup 'RED' with '/red_color'.
Declaring a static map
and loading the enum
s into it only once would bring some performance benefits if the enum
s are many.
也许,看看这个。它为我工作。这样做的目的是使用“/red_color”查找“RED”。如果s 很多,声明 astatic map
并将enum
s加载到其中一次会带来一些性能优势enum
。
public class Mapper {
public enum Maps {
COLOR_RED("/red_color", "RED");
private final String code;
private final String description;
private static Map<String, String> mMap;
private Maps(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return name();
}
public String getDescription() {
return description;
}
public String getName() {
return name();
}
public static String getColorName(String uri) {
if (mMap == null) {
initializeMapping();
}
if (mMap.containsKey(uri)) {
return mMap.get(uri);
}
return null;
}
private static void initializeMapping() {
mMap = new HashMap<String, String>();
for (Maps s : Maps.values()) {
mMap.put(s.code, s.description);
}
}
}
}
Please put in your opinons.
请提出您的意见。
回答by Mayank Butpori
You can use the Enum::valueOf()
function as suggested by Gareth Davis & Brad Mace above, but make sure you handle the IllegalArgumentException
that would be thrown if the string used is not present in the enum.
您可以Enum::valueOf()
按照上面 Gareth Davis 和 Brad Mace 的建议使用该函数,但请确保您处理了IllegalArgumentException
如果使用的字符串不存在于枚举中时将抛出的 。
回答by Vinay Sharma
You can define your Enum as following code :
您可以将 Enum 定义为以下代码:
public enum Verbosity
{
BRIEF, NORMAL, FULL, ACTION_NOT_VALID;
private int value;
public int getValue()
{
return this.value;
}
public static final Verbosity getVerbosityByValue(int value)
{
for(Verbosity verbosity : Verbosity.values())
{
if(verbosity.getValue() == value)
return verbosity ;
}
return ACTION_NOT_VALID;
}
@Override
public String toString()
{
return ((Integer)this.getValue()).toString();
}
};
回答by Lam Le
with Java 8 you can achieve with this way:
使用 Java 8,您可以通过以下方式实现:
public static Verbosity findByAbbr(final String abbr){
return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}
回答by Chad Befus
In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:
如果它对其他人有帮助,我更喜欢的选项(此处未列出)使用Guava 的 Maps 功能:
public enum Vebosity {
BRIEF("BRIEF"),
NORMAL("NORMAL"),
FULL("FULL");
private String value;
private Verbosity(final String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
private static ImmutableMap<String, Verbosity> reverseLookup =
Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue);
public static Verbosity fromString(final String id) {
return reverseLookup.getOrDefault(id, NORMAL);
}
}
With the default you can use null
, you can throw IllegalArgumentException
or your fromString
could return an Optional
, whatever behavior you prefer.
使用默认值,您可以使用null
,您可以throw IllegalArgumentException
或您fromString
可以返回Optional
,无论您喜欢什么行为。
回答by Adrian
since java 8 you can initialize the map in a single line and without static block
从 Java 8 开始,您可以在一行中初始化地图,而无需静态块
private static Map<String, Verbosity> stringMap = Arrays.stream(values())
.collect(Collectors.toMap(Enum::toString, Function.identity()));