Introduction

Let us learn about the EnumUtils from the Apache Commons Lang library. The EnumUtils class has several static methods (helper methods) for Java enums.

Getting Apache Commons Lang3

When using Maven, you can import the Commons Lang as:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

You can replace 3.12.0 with the latest version available from Maven.

For Gradle,

implementation 'org.apache.commons:commons-lang3:3.12.0'

Example enum for EnumUtils

In this post, we will use the Color enum shown below.

public enum Color {
    BLUE("Blue"),
    RED("Red"),
    YELLOW("Yellow"),
    BLACK("Black");

    private final String color;

    Color(String color) {
        this.color = color;
    }
}

EnumUtils getEnumList and getEnumMap

The getEnumList method takes the class of the enum and returns the list of enums. Its method signature is,

public static <E extends Enum<E>> List<E> getEnumList(final Class<E> enumClass)
System.out.println(EnumUtils.getEnumList(Color.class));

Prints,

[BLUE, RED, YELLOW, BLACK]

The output is the same as what Color.values() would return, but as a list. Color.values returns an array (Color[]).

The getEnumMap takes the class of the enum and returns the map of enums by name.

public static <E extends Enum<E>> Map<String, E> getEnumMap(final Class<E> enumClass) 
System.out.println(EnumUtils.getEnumMap(Color.class));

This would return the map as:

{BLUE=BLUE, RED=RED, YELLOW=YELLOW, BLACK=BLACK}

The map’s key is the enum’s name, and the value is the string returned by the enum’s toString.

A note on enum name vs toString

The default implementation of an enum’s toString would return the name of the enum itself (which is the name of the enum constant, exactly as declared in its enum declaration). Let us say we add toString() method to the Color enum as shown below to return the value in the color field.

@Override
public String toString() {
    return color;
}

Now, calling EnumUtils.getEnumMap(Color.class) will return,

{BLUE=Blue, RED=Red, YELLOW=Yellow, BLACK=Black}

The key is the enum’s name (which didn’t change from before) and the value is the enum’s toString.

EnumUtils getEnum and getEnumIgnoreCase

Before we look into the getEnum method, a quick refresher on Enum.valueOf method. As we have seen before, the name() method on an enum will return the name of the enum constant.

System.out.println(Color.BLUE.name()); //BLUE

The Enum.valueOf() method takes the enum class and the name of the enum constant to return (a string) and returns the enum constant of the specified enum class with the specified name.

System.out.println(Enum.valueOf(Color.class, "BLUE")); //BLUE

Here, the passed name must exactly match the enum constant declaration in the enum. If we pass a value which doesn’t match with any of the enum constants, it will throw an IllegalArgumentException. Both of the below calls will throw an IllegalArgumentException.

//throws java.lang.IllegalArgumentException
System.out.println(Enum.valueOf(Color.class, "Blue"));
System.out.println(Enum.valueOf(Color.class, "ORANGE"));

getEnum method

The getEnum method takes the class of the enum and the enum name to query and returns the enum instance if found. If not found, it will return a null. This method’s behaviour is different from Enum.valueOf in that it doesn’t throw an exception when we pass an invalid enum name.

System.out.println(EnumUtils.getEnum(Color.class, "BLUE")); //BLUE
System.out.println(EnumUtils.getEnum(Color.class, "Blue")); //null
System.out.println(EnumUtils.getEnum(Color.class, "ORANGE")); //null

In the above example, in the first call, when we pass the enum name as “BLUE”, it returns the enum instance Color.BLUE. But still it is case-sensitive. If we pass “Blue”, it returns a null. Finally, it returns a null for a non-existing enum name.

There is an overloaded getEnum() method to which we can pass an additional parameter, the default enum value. If the passed enum value is not found in the enum, then it will return this default enum value.

// getEnum with default enum
System.out.println(EnumUtils.getEnum(Color.class, "BLUE", Color.BLACK)); //BLUE
System.out.println(EnumUtils.getEnum(Color.class, "Blue", Color.BLACK)); //BLACK
System.out.println(EnumUtils.getEnum(Color.class, "ORANGE", Color.BLACK)); //BLACK

In the last two calls, since the passed enum value wouldn’t match any of the enum constants, it returns the passed default enum value (Color.BLACK).

getEnumIgnoreCase method

The getEnumIgnoreCase method is similar to the getEnum method, but it works by matching the passed enum name with enum constants in a case insensitive manner.

System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "BLUE")); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "Blue")); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "BlUE")); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "ORANGE")); //null

Irrespective of what case the characters in the string “Blue” are, it will always match it with the enum Color.BLUE and returns it. Hence, the only time it would return a null is when we pass an enum value which doesn’t exist.

Similar to the getEnum method overload taking a default enum, there is an overloaded method for getEnumIgnoreCase as well to which we can pass a default enum to return when there is no match (i.e., for cases where it would return a null, it will return this default enum).

// getEnumIgnoreCase with default enum
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "BLUE", Color.BLACK)); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "Blue", Color.BLACK)); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "BlUE", Color.BLACK)); //BLUE
System.out.println(EnumUtils.getEnumIgnoreCase(Color.class, "ORANGE", Color.BLACK)); //BLACK

EnumUtils isValidEnum and isValidEnumIgnoreCase

isValid

The isValid method of the EnumUtils checks if the specified name is a valid enum of an enum class. It takes the enum class and the enum name and returns true if the enum name is valid.

System.out.println(EnumUtils.isValidEnum(Color.class, "BLUE")); //true
System.out.println(EnumUtils.isValidEnum(Color.class, "Blue")); //false
System.out.println(EnumUtils.isValidEnum(Color.class, null)); //false

In the first example, BLUE is valid enum value, and it returned a true. It doesn’t match in a case insensitive way and hence it returned a false for the enum value “Blue”. If we pass null, it will return false.

isValidEnumIgnoreCase

The isValidEnumIgnoreCase does the same thing as isValid but it does the check in a case insensitive way. Examples are shown below.

System.out.println(EnumUtils.isValidEnumIgnoreCase(Color.class, "BLUE")); //true
System.out.println(EnumUtils.isValidEnumIgnoreCase(Color.class, "Blue")); //true
System.out.println(EnumUtils.isValidEnumIgnoreCase(Color.class, null)); //false

The difference is in the second call - it returns true for the enum value “Blue” as it matches to the enum constant Color.BLUE.

EnumUtils generateBitVector and generateBitVectors

generateBitVector

We use the generateBitVector to create a long bit vector representation of the given array of Enum values. We can pass the enum values as a var-args or as an Iterable (there are two overloaded methods as shown below).

public static <E extends Enum<E>> long generateBitVector(
      final Class<E> enumClass, final E... values)
public static <E extends Enum<E>> long generateBitVector(
      final Class<E> enumClass, final Iterable<? extends E> values)

A long in Java can have 64 bits. Thus, think of initializing a long to zero (i.e., each of those bits set to zero). Then, for each enum value we pass, it sets the appropriate bit in that.

The first enum constant (as per the declaration order) would correspond to the least significant bit (i.e., the rightmost bit). The second enum constant would be the second bit from the right, and so on. If the first enum value is passed, then it sets the rightmost bit to 1; otherwise, it remains 0. If we pass the second enum value, it sets the second bit from the right to 1 and so on. Finally, the long value derived by converting this 64 bit binary to long will be returned.

NOTE: We should not use this method if we have more than 64 values in the enum. It will throw an IllegalArgumentException if it has more than 64 values.

Examples for EnumUtils generateBitVector

Let us start with a simple example. We pass the first enum constant (Color.BLUE). This will result in a binary value of 1 (least significant bit is 1) and hence it returns 1.

System.out.println(EnumUtils.generateBitVector(Color.class, Color.BLUE)); //1

Passing BLUE and RED will set the last two bits to 1, resulting in a binary value of 11, which is 3 as a long.

System.out.println(EnumUtils.generateBitVector(Color.class, Color.BLUE, Color.RED)); //3

The order in which we pass those values doesn’t matter. Passing RED and BLUE would result in 3 as well.

System.out.println(EnumUtils.generateBitVector(Color.class, Color.RED, Color.BLUE)); //3
  • Passing BLUE, YELLOW and BLACK would create a bit representation of 1101, which is 13.
  • Passing all the enum values would create a bit representation of 1111, which is 15.
System.out.println(EnumUtils.generateBitVector(Color.class, Color.BLUE, Color.YELLOW, Color.BLACK)); //13
System.out.println(EnumUtils.generateBitVector(Color.class, Color.RED, Color.BLUE, Color.YELLOW, Color.BLACK)); //15

We could also pass the enums as an Iterable as shown below.

List<Color> colors = List.of(Color.BLUE, Color.RED);
System.out.println(EnumUtils.generateBitVector(Color.class, colors)); //3

generateBitVectors

If we have more than 64 values in the enum, we have to use the generateBitVectors method. It creates a bit vector representation of the given enum constant values using as many longs as needed.

It will return a long[] whose values provide a binary representation of the passed enums with the least significant digits rightmost.

Think of dividing the enum constants (as declared) into groups of 64. For each of the group, it calculates the long value (binary bit vector representation) as explained previously for the generateBitVector method. Then, it returns each of the long values from each of the groups as a long[].

  • For the first 64 enums, it computes the long and places it in the 0th index of the long[]
  • For the next 64 enums, it computes the long and places it in the 1st index of the long[]
  • and so on

Since the Color enum has lesser than 64 values, the results would be the same as using the generateBitVector method.

System.out.println(Arrays.toString(EnumUtils.generateBitVectors(Color.class, Color.BLUE))); //[1]
System.out.println(Arrays.toString(EnumUtils.generateBitVectors(Color.class, Color.BLUE, Color.RED))); //[3]
System.out.println(Arrays.toString(EnumUtils.generateBitVectors(Color.class, Color.RED, Color.BLUE, Color.YELLOW, Color.BLACK))); //[15]

We can pass the enums as an Iterable as well as shown below.

System.out.println(Arrays.toString(EnumUtils.generateBitVectors(Color.class, colors))); // [3]

EnumUtils processBitVector method

The processBitVector and processBitVectors method does the inverse of what generateBitVector and generateBitVectors method. Using these, we can convert the long value or the long[] value into a set of enum values that it represents.

processBitVector

The examples shown are self-explanatory. We pass the long values created out of the generateBitVector to get back a EnumSet of enums.

System.out.println(EnumUtils.processBitVector(Color.class, 1)); //[BLUE]
System.out.println(EnumUtils.processBitVector(Color.class, 3)); //[BLUE, RED]
System.out.println(EnumUtils.processBitVector(Color.class, 13)); //[BLUE, YELLOW, BLACK]
System.out.println(EnumUtils.processBitVector(Color.class, 15)); //[BLUE, RED, YELLOW, BLACK]

If we pass an invalid value, it returns an empty set.

System.out.println(EnumUtils.processBitVector(Color.class, 16)); //[]

processBitVectors

The processBitVectors takes a var-args of long (long[]) created out of generateBitVectors method.

System.out.println(EnumUtils.processBitVectors(Color.class, 1)); //[BLUE]
System.out.println(EnumUtils.processBitVectors(Color.class, 3)); //[BLUE, RED]
System.out.println(EnumUtils.processBitVectors(Color.class, 13)); //[BLUE, YELLOW, BLACK]
System.out.println(EnumUtils.processBitVectors(Color.class, 15)); //[BLUE, RED, YELLOW, BLACK]

Since our example enum doesn’t have more than 64 values, it doesn’t make sense to pass more than one long value. However, even if we did, it considers only the last long value.

//each element in long[] is for each block of 64 values.
System.out.println(EnumUtils.processBitVectors(Color.class, 15, 13, 3)); //[BLUE, RED]
System.out.println(EnumUtils.processBitVectors(Color.class, 15, 13, 3, 1)); //[BLUE]

Conclusion

In this post, we learnt about the EnumUtils class from the Apache Commons Lang library. Check out the other apache-commons library utilities.

Useful references