添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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);
                IIRC, that gives an NPE because the static initialisation is done top down (i.e. the enum constants at the top are constructed before it gets down to the stringMap initialisation). The usual solution is to use a nested class.
– Tom Hawtin - tackline
                Jul 3, 2009 at 21:36
                Thank you everyone for such rapid response. (FWIW I didn't find the Sun Javadocs very useful for this problem).
– peter.murray.rust
                Jul 3, 2009 at 21:45
                It's really a language issue than a library issue. However, I think the API docs are read more than the JLS (although perhaps not by language designers), so things like this should probably have more prominence in the java.lang docs.
– Tom Hawtin - tackline
                Jul 3, 2009 at 22:37

Use the valueOf method which is automatically created for each 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.

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.

You can directy access the class member 'abbr' so instead of "v.abbr()" you can use "v.abbr.equals...". – Amio.io Apr 19, 2015 at 12:08 Also, for arbitrary values (the second case) consider throwing an IllegalArgumentException instead of returning null (i.e. when no match is found) - this is how the JDK Enum.valueOf(..) does it, anyway. – Priidu Neemre May 21, 2015 at 17:28 @Gareth Davis I think EnumSet.allOf(Verbosity.class) is probably better than values() which creates a new array on the heap every time! – Adam Gent Nov 12, 2020 at 18:33 @Adam Gent which in turn will create an object on the heap... doubt very much if you’d ever notice the difference in anything other than insanely sensitive code – Gareth Davis Nov 13, 2020 at 22:27 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); Due to classloader issues this method will not work reliable. I do not recommend it and I have seen it fail regularly because the lookup map is not ready before being accessed. You need to put the "lookup" outside of the enum or in another class so that it will load first. – Adam Gent Jul 18, 2012 at 16:00 @Adam Gent: There's a link down below to the JLS where this exact construct is posed as an example. It says that static initialization occurs from top to bottom: docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#d5e12267 – Selena Oct 15, 2014 at 18:22 Yes modern java like java 8 has fixed the memory model. That being said hot swap agents like jrebel still get messed up if you embed the initialization because of circular references. – Adam Gent Oct 16, 2014 at 15:49 @Adam Gent: Hmmm. I learn something new every day. [Quietly slinking off to refactor my enums with bootstrap singletons ...] Sorry if this is a stupid question, but is this mostly a problem with static initialization? – Selena Oct 18, 2014 at 15:15 I've never seen issues with the static code block not being initialized, but I have only used Java 8 since I started in Java, in 2015. I just did a little benchmark using JMH 1.22 and using a HashMap<> to store the enums proved to be over 40% faster than a foor loop. – cbaldan Dec 3, 2019 at 16:18

with Java 8 you can achieve with this way:

public static Verbosity findByAbbr(final String abbr){
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
                I would throw an exception rather than returning null. But it is also depending on the use case
– alexander
                Apr 10, 2019 at 14:19
                @alexander both null and exception should be catched and solved in the follow-up stream properly, no matter which step should take
– Harry_T
                Aug 26, 2022 at 6:41

@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.

Edit this 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.

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.

Need to define "dangerous" and why an inner class implementation matters. It is more of a top-to-bottom static definition issue but there is working code in another related answer with link back to this question that uses a static Map on the Enum instance itself with a "get" method from user-defined value to Enum type. stackoverflow.com/questions/604424/lookup-enum-by-string-value – Darrell Teague Jun 15, 2016 at 19:30 @DarrellTeague the original issue was due to old JVMs (pre 1.6) or other JVMs (IBMs) or hotcode swappers (JRebel). The issue should not happen in modern JVMs so I may just delete my answer. – Adam Gent Jun 15, 2016 at 20:24 Good to note that indeed it is possible due to custom compiler implementations and runtime optimizations... the ordering could be resequenced, resulting in an error. However, this would appear to violate the spec. – Darrell Teague Jun 17, 2016 at 16:33 Or the synthetic valueOf on the enum class, so you don't need to specify the enum class Class. – Tom Hawtin - tackline Jul 3, 2009 at 21:34 You can use valueOf() but the name must match identically to that set in the enum declaration. Either of the two lookup methods above can be modified to use .equalsIgnoringCase() and have little more robustness to error. – user1239282 Jun 22, 2012 at 2:15 @leonardo True. If it adds robustness or just fault-tolerance is debatable. In most cases I would say it is the latter and in that case it is better to handle it elsewhere and still use Enum's valueOf(). – Fredrik Jun 24, 2012 at 8:39

In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:

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.

since java 8 you can initialize the map in a single line and without static block

private static Map<String, Verbosity> stringMap = Arrays.stream(values())
                 .collect(Collectors.toMap(Enum::toString, Function.identity()));
                +1 Excellent use of streams, and very concise without sacrificing readability! I had also not seen this use of Function.identity() before, I find it much more textually appealing than e -> e.
– Matsu Q.
                Jun 2, 2020 at 16:36
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);

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 enums into it only once would bring some performance benefits if the enums are many.

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.

If you want a default value and don't want to build lookup maps, you can create a static method to handle that. This example also handles lookups where the expected name would start with a number.

    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;

If you need it on a secondary value, you would just build the lookup map first like in some of the other answers.

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();

See following link for more clarification