Getting all names in an enum as a String[]

163,493

Solution 1

Here's one-liner for any enum class:

public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
}

Pre Java 8 is still a one-liner, albeit less elegant:

public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.toString(e.getEnumConstants()).replaceAll("^.|.$", "").split(", ");
}

That you would call like this:

String[] names = getNames(State.class); // any other enum class will work

If you just want something simple for a hard-coded enum class:

public static String[] names() {
    return Arrays.toString(State.values()).replaceAll("^.|.$", "").split(", ");
}

Solution 2

Create a String[] array for the names and call the static values() method which returns all the enum values, then iterate over the values and populate the names array.

public static String[] names() {
    State[] states = values();
    String[] names = new String[states.length];

    for (int i = 0; i < states.length; i++) {
        names[i] = states[i].name();
    }

    return names;
}

Solution 3

Here`s an elegant solution using Apache Commons Lang 3:

EnumUtils.getEnumList(State.class)

Although it returns a List, you can convert the list easily with list.toArray()

Solution 4

If you can use Java 8, this works nicely (alternative to Yura's suggestion, more efficient):

public static String[] names() {
    return Stream.of(State.values()).map(State::name).toArray(String[]::new);
}

Solution 5

With java 8:

Arrays.stream(MyEnum.values()).map(Enum::name)
                    .collect(Collectors.toList()).toArray();
Share:
163,493

Related videos on Youtube

Konstantin
Author by

Konstantin

Updated on April 24, 2021

Comments

  • Konstantin
    Konstantin about 3 years

    What's the easiest and/or shortest way possible to get the names of enum elements as an array of Strings?

    What I mean by this is that if, for example, I had the following enum:

    public enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
    
        public static String[] names() {
            // ...
        }
    }
    

    the names() method would return the array { "NEW", "RUNNABLE", "BLOCKED", "WAITING", "TIMED_WAITING", "TERMINATED" }.

    • marcolopes
      marcolopes about 10 years
      Why there is not a native Enum method that does exactly that it's beyond me... and also a get(index) to simplify the get of value()
  • JB Nizet
    JB Nizet over 11 years
    Why call values() 13 times, generating a new array each time, instead of caching the array in a local variable? Why use toString(), which is overridable, instead of name()?
  • PermGenError
    PermGenError over 11 years
    @JBNizet heheh, i actually tried this in my IDE and way to lazy to create an State array i guess, hehe, anyways iedited it now :)
  • JB Nizet
    JB Nizet over 11 years
    You're still not returning the names, but the toString() values.
  • PermGenError
    PermGenError over 11 years
    @JBNizet hmm, tbh, i dint really know there was a name() method untill now. how stupid of me :P thanks for letting me know :)
  • FThompson
    FThompson over 11 years
    Although it doesn't particularly matter, a regular for loop offers better performance than a foreach loop in this situation. Plus, values() is called twice when it need only be called once.
  • Konstantin
    Konstantin over 11 years
    @Vulcan I think performance would only be an issue with this if it were run hundreds of thousands of times. Besides, values() is a method generated by the compiler, so I'm guessing it's pretty optimized. Finally, I remember reading somewhere that for-each loops are more efficient than standard, incremental for loops, but then again — it just doesn't matter.
  • Konstantin
    Konstantin over 11 years
    I'd do something like this as well if I needed to repeatedly get the enum names, but since the names() method is only called sparingly, I think generating an array on the spot is fine.
  • Bohemian
    Bohemian over 11 years
    Not the shortest :) See my answer for a one-liner (that still only invokes vales() once)
  • ceklock
    ceklock over 11 years
    Not the fastest ways to do the job, but nice regex.
  • Konstantin
    Konstantin over 11 years
    I accepted this answer, but I submitted an edit that improves the code so it's easier to read.
  • sage88
    sage88 over 9 years
    @Konstantin considering that the foreach loop in java is implemented with a standard for loop, where ever you read that foreach loops are ever more efficient is incorrect.
  • Konstantin
    Konstantin over 9 years
    @sage88 I was referring to for loops in which you retrieve elements using a numeric index, which you increment in each cycle. For example: for (int i = 0; i < a.length; i++) /* do stuff */; In this case, for-each loops are, in fact, more efficient. A quick SO search on the matter gives us this: stackoverflow.com/questions/2113216/…
  • sage88
    sage88 over 9 years
    @Konstantin Any time you have a data structure that allows random access, as is the case with enum values, which returns an array, a C-style for loop is faster than using a for each loop. The for each loop has to generate an iterator, which makes it slower. The link you posted gives an example of using a standard for loop on a linked list using get(i), which is of course worse. When using a non-random access data structure the for each loop is faster, but on arrays it has a greater overhead. Also, since it's a primitive array, not an ArrayList, there's no performance hit from .size().
  • sage88
    sage88 over 9 years
    Though I should say that I was wrong above, for each does't use a standard for loop, it uses an iterator.
  • Daniel Bimschas
    Daniel Bimschas about 9 years
    While it probably works, this implementation is quite inefficient, first creating an ArrayList, adding all elements, then creating an array and copying everything again.
  • marcolopes
    marcolopes about 9 years
    Any time soon "everyone" will be using streams to accomplish the most basic operations... and that is not a very good idea.
  • Aquarius Power
    Aquarius Power about 8 years
    and java7 compliant!
  • Eido95
    Eido95 over 7 years
    In Java 8 solution, outside a method scope, instead of e.getEnumConstants() you may use YourEnumName.values()
  • Bohemian
    Bohemian over 7 years
    @Eido95 using YourEnumName.values() is calling a static method on the class, which cannot be reused for any enum. Using getEnumConstants() works for any enum class. The idea with this method is to recreate a utility method that you can call like the last line of the answer.
  • Dan Halbert
    Dan Halbert over 7 years
    EnumUtils.getEnumList(enumClass) returns the enum values, not the Strings. You could use EnumUtils.getEnumMap(enumClass).keySet(), but the order might be different.
  • stefan.m
    stefan.m over 7 years
    considering the fact that the number of elements in enums is usually rather small, I think that Yura's solution will be fine for many use cases. Naturally, it will depend on the specific situation...
  • cosimo193
    cosimo193 over 7 years
    Any reason not to use ordinal() for the index and a for each loop, like: for (State state: State.values() { names[state.ordinal()] = state.toString(); }
  • Stephan
    Stephan about 7 years
    What is EnumUtils?
  • Bohemian
    Bohemian over 6 years
    In this case toString() works, but in the general case it does not, because toString() can be be overridden. Use .name() to reliably get the instance name as a String.
  • nedlud
    nedlud almost 6 years
    Shouldn't it be State[] states = State.values();
  • Rauni Lillemets
    Rauni Lillemets over 5 years
    You should give the statistics about performance, then people can judge for themselves if the performance loss is significant or not. I suppose that most people will not have 100+ or 1000+ values for an Enum.
  • Karen Goh
    Karen Goh over 5 years
    @PermGenError, I would like to know how to return the values (English, L1) , L1 being the value; after comparing the arrays of string with the Enums arrays. For example, the String Arrays contains English, etc etc, but I want to return a list of L1, L2 etc if it matches the ones in the Enums.
  • Line
    Line over 5 years
  • Line
    Line over 5 years
    @wutzebaer downvoting because this soultion isn't complete - it doesn't return array
  • ralphgabb
    ralphgabb over 5 years
    if you want a custom label for your enum, override toString() in your enum class.
  • Carmageddon
    Carmageddon over 4 years
    Can you please explaing Class<? extends Enum<?>> e?
  • Bohemian
    Bohemian over 4 years
    @Carmageddon Class<? extends Enum<?>> e basically means "any enum class", and in more detail means e is a Class whose type is (or is a subtype of) Enum<?>. All enum classes implicitly extend the Enum class, whose type is a self-referencing type, ie Enum<E extends Enum<E>>
  • EngNjuguna
    EngNjuguna about 3 years
    Create a new String array. You can then populate it with values() from your enum by using the enhanced for-loop to loop through the enum.
  • Boško Bezik
    Boško Bezik about 3 years
    No need to use Streams. A simple for loop and a temporary array would do the trick.
  • Bohemian
    Bohemian about 3 years
    @BoškoBezik there’s no need to ever use streams for anything, but they make the code neater and hopefully easier to read, which is code’s purpose.