簡體   English   中英

如何從 String 值中查找 Java 枚舉?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM