103

Is there any Java 8 method or easy way, which returns Enum values as a List of String, like:

List<String> sEnum = getEnumValuesAsString();
Radiodef
  • 37,180
  • 14
  • 90
  • 125

3 Answers3

221

You can do (pre-Java 8):

List<Enum> enumValues = Arrays.asList(Enum.values());

or

List<Enum> enumValues = new ArrayList<Enum>(EnumSet.allOf(Enum.class));

Using Java 8 features, you can map each constant to its name:

List<String> enumNames = Stream.of(Enum.values())
                               .map(Enum::name)
                               .collect(Collectors.toList());
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • Great answer. Is there any downside of using stream over array to list considering runtime? – Hannes Apr 06 '15 at 05:51
  • 1
    No. Using Streams can actually improve performance, as it can be processed in parallel. – Konstantin Yovkov Apr 06 '15 at 05:53
  • 8
    You can also shorten `asList(...).stream()` slightly by using `Stream.of` or `Arrays.stream`. – Radiodef Apr 06 '15 at 05:56
  • 19
    @kocko: That's an oversimplification. For small amounts of data, streams will usually have a small overhead over arrays, and use of `parallel` can significantly _hurt_ performance; parallelization has a cost that's not always outweighed by the wins. – Louis Wasserman Apr 06 '15 at 18:47
  • 4
    First and second solution don't really solve the problem, since OP is asking for array of strings as result. So streams are the only viable solution? – kikovi Jan 10 '16 at 22:25
  • 6
    To join the names into one string so you can log them, replace the collector with `.collect(Collectors.joining(", "))`. – Noumenon Jun 29 '17 at 23:53
  • @kikovi yes it probably is only solution to fit OP answer, but your comment about Streams not capable of hurting performance is not true – Brandon Ling May 22 '18 at 13:25
  • How would you be able to get the names of the Enums into a list? Like `AnimalA("Cow"), AnimalB("Dog")` etc? I want the name, not the name of the Enum itself. – SovietFrontier Oct 04 '19 at 19:55
12

You could also do something as follow

public enum DAY {MON, TUES, WED, THU, FRI, SAT, SUN};
EnumSet.allOf(DAY.class).stream().map(e -> e.name()).collect(Collectors.toList())

or

EnumSet.allOf(DAY.class).stream().map(DAY::name).collect(Collectors.toList())

The main reason why I stumbled across this question is that I wanted to write a generic validator that validates whether a given string enum name is valid for a given enum type (Sharing in case anyone finds useful).

For the validation, I had to use Apache's EnumUtils library since the type of enum is not known at compile time.

@SuppressWarnings({ "unchecked", "rawtypes" })
public static void isValidEnumsValid(Class clazz, Set<String> enumNames) {
    Set<String> notAllowedNames = enumNames.stream()
            .filter(enumName -> !EnumUtils.isValidEnum(clazz, enumName))
            .collect(Collectors.toSet());

    if (notAllowedNames.size() > 0) {
        String validEnumNames = (String) EnumUtils.getEnumMap(clazz).keySet().stream()
            .collect(Collectors.joining(", "));

        throw new IllegalArgumentException("The requested values '" + notAllowedNames.stream()
                .collect(Collectors.joining(",")) + "' are not valid. Please select one more (case-sensitive) "
                + "of the following : " + validEnumNames);
    }
}

I was too lazy to write an enum annotation validator as shown in here https://stackoverflow.com/a/51109419/1225551

Raf
  • 7,505
  • 1
  • 42
  • 59
0

If you need to go to an array, you can do this:

public enum DAY {MON, TUES, WED, THU, FRI, SAT, SUN};

String[] days = Stream.of(DAY.values()).map(Enum::name).toArray(String[]::new);
Craigo
  • 3,384
  • 30
  • 22