[英]How can I lookup a Java enum from its String value?
我想從其字符串值(或可能的任何其他值)中查找枚舉。 我已經嘗試了以下代碼,但它不允許在初始化程序中使用靜態。 有沒有簡單的方法?
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);
}
};
使用為每個 Enum 自動創建的valueOf
方法。
Verbosity.valueOf("BRIEF") == Verbosity.BRIEF
對於任意值,開頭為:
public static Verbosity findByAbbr(String abbr){
for(Verbosity v : values()){
if( v.abbr().equals(abbr)){
return v;
}
}
return null;
}
如果您的分析器告訴您,請稍后再轉到 Map 實現。
我知道它正在迭代所有的值,但只有 3 個枚舉值幾乎不值得做任何其他的努力,事實上,除非你有很多值,否則我不會打擾 Map 它會足夠快。
你很接近。 對於任意值,請嘗試以下操作:
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);
}
}
使用 Java 8,您可以通過以下方式實現:
public static Verbosity findByAbbr(final String abbr){
return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}
@Lyle 的回答相當危險,我發現如果您將枚舉設置為靜態內部類,它就不起作用。 相反,我使用了這樣的東西,它將在枚舉之前加載 BootstrapSingleton 映射。
使用現代 JVM(JVM 1.6 或更高版本)編輯這應該不再是問題,但我確實認為 JRebel 仍然存在問題,但我還沒有機會重新測試它。
先加載我:
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>();
}
現在在枚舉構造函數中加載它:
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);
}
}
如果你有一個內部枚舉,你可以在枚舉定義上方定義 Map 並且(理論上)應該在之前加載。
你不能使用valueOf()嗎?
編輯:順便說一句,沒有什么可以阻止您在枚舉中使用 static { } 。
在Java語言規范7中有一個例子 ! 這反映了您使用自引用初始化地圖的問題。
如果它對其他人有幫助,我更喜歡的選項(此處未列出)使用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);
}
}
默認情況下,您可以使用null
,您可以throw IllegalArgumentException
或者您的fromString
可以返回一個Optional
,無論您喜歡什么行為。
從 Java 8 開始,您可以在一行中初始化地圖,而無需靜態塊
private static Map<String, Verbosity> stringMap = Arrays.stream(values())
.collect(Collectors.toMap(Enum::toString, Function.identity()));
public enum EnumRole {
ROLE_ANONYMOUS_USER_ROLE ("anonymous user role"),
ROLE_INTERNAL ("internal role");
private String roleName;
public String getRoleName() {
return roleName;
}
EnumRole(String roleName) {
this.roleName = roleName;
}
public static final EnumRole getByValue(String value){
return Arrays.stream(EnumRole.values()).filter(enumRole -> enumRole.roleName.equals(value)).findFirst().orElse(ROLE_ANONYMOUS_USER_ROLE);
}
public static void main(String[] args) {
System.out.println(getByValue("internal role").roleName);
}
}
也許,看看這個。 它為我工作。 這樣做的目的是使用“/red_color”查找“RED”。 如果enum
很多,聲明一個static map
並將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);
}
}
}
}
請提出您的意見。
如果您想要一個默認值並且不想構建查找映射,您可以創建一個靜態方法來處理它。 此示例還處理預期名稱以數字開頭的查找。
public static final Verbosity lookup(String name) {
return lookup(name, null);
}
public static final Verbosity lookup(String name, Verbosity dflt) {
if (StringUtils.isBlank(name)) {
return dflt;
}
if (name.matches("^\\d.*")) {
name = "_"+name;
}
try {
return Verbosity.valueOf(name);
} catch (IllegalArgumentException e) {
return dflt;
}
}
如果您需要在次要值上使用它,您只需像在其他一些答案中一樣首先構建查找圖。
您可以將 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();
}
};
您可以按照上面 Gareth Davis 和 Brad Mace 的建議使用Enum::valueOf()
函數,但請確保您處理了IllegalArgumentException
,如果使用的字符串不存在於枚舉中,則會拋出該異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.