Ten minute tutorial

EnumSet in Java - RegularEnumSet vs JumboEnumSet

EnumSet in Java is a special implementation of Set interface added back in Java 1.5, when Enum was first introduced into the Java Programming language. Surprisingly so many years after the Java 1.5 release (released 30th September 2004, codenamed Tiger), a lot of Java programmers are still unaware of several good features that were introduced. EnumSet is one of such example which can be really useful and provides greater performance when compared to other Set implementations for Enum constants. When I discussed EnumMap in Java on my blog I wanted to mention EnumSet as well, but couldn't find the time. However, reading a recent Interview question about How EnumSet is implemented in Java from one of my readers triggered this post. Indeed, EnumSet is becoming popular in Java interviews because of its high performance and specialized use with Enum constants. In this Java tutorial, we will talk about what EnumSet means for Java, how it's implemented in the form of RegularEnumSet and JumboEnumSet and most importantly when to use EnumSet in Java.

What is EnumSet

As mentioned previously, it's a special implementation of Set interface, which means you can pass it to a method, which accepts Set interface as a parameter. EnumSet can only be used with Enum constants, which means you can not store any other object in EnumSet. EnumSet also presents a good example of the Factory method design pattern to create instances.

It enforces the use of Factory method by declaring EnumSet as an abstract classand making its concrete implementation RegularEnumSet and JumboEnumSet package-private. This means you can neither create an instance of EnumSet nor any of its implementations. This kind of of enforcement is good, if you provide different Factory methods for different needs. EnumSet is right on the money there as you can see methods like EnumSet.of(E...), which creates EnumSet of elements provided to it.

This is an excellent use of method overloading and variable arguments. EnumSet.of() method is overloaded for common usage, which tends to perform better than variable argument version, and can be added for flexibility to create enum with any number of instances. Additionally EnumSet provides methods like copyOf(), noneOf() to create EnumSet by copying elements from other collections, and creating empty EnumSet of a particular Enum type in Java.

How EnumSet is implemented in Java

EnumSet is an abstract class and it provides two concrete implementations, java.util.RegularEnumSet and java.util.JumboEnumSet. The main difference between the two is that the former uses a long variable to store elements while later uses a long[] to store its element. Since RegularEnumSet uses long variable, which is a 64 bit data type, it can only hold that much of an element. That's why when an empty EnumSet is created using EnumSet.noneOf()method. It chooses RegularEnumSet if the key universe (number of enum instances in Key Enum) is less than or equal to 64. It chooses JumboEnumSet if the key universe is more than 64. Here is the code which does that :

 

 public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
     
        .. ............
        if (universe.length <= 64)
            return new RegularEnumSet<E>(elementType, universe);
        else
            return new JumboEnumSet<E>(elementType, universe);
    }

 

Though this is a pretty low level implementation in detail, it's always good to know about it to impress in an job interview if you were asked the question.

When to use EnumSet in Java

Joshua Bloch has mentioned an interesting use case scenario for EnumSet in Item 32 of his Java Classic Effective Java. This item advises us to use EnumSet in the place of bit fields, which is part of enum int pattern. In enum int pattern, different enum constants are represented as power of 2 and later combined using bitwise operators. I strongly suggest looking that example mentioned in the book; it's very clear and quite useful as well. Now back to general usage - whenever you need to group certain enums for a meaningful purpose, you can use EnumSet e.g. if you have an enum to represent DayOfWeek, you can use EnumSet to create WEEKDAYS and WEEKEND, instead of defining separate enum for that example. So,

 

private enum DayOfWeek{

MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

}



private EnumSet weekend = EnumSet.of(SATURDAY,SUNDAY);

 

Similarly, months of year can be logically grouped into different seasons e.g. Summer, Winter as shown below :

 

enum Month{

JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,

AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;

}



EnumSet summer = EnumSet.of(Month.MARCH, Month.APRIL, Month.MAY, Month.JUNE);



EnumSet winter = EnumSet.of(Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER, Month.JANUARY);

 

So, apart from using EnumSet in the place of enum int pattern, you can also use it to a create logical grouping of different instances of a single enum type.

Important points about EnumSet

Here are some worthwhile things to know about EnumSet in Java. Like all other collection classes, I strongly recommend getting familiar with the specifics of EnumSet before using it in production code.

  1. EnumSet can only be created of a single enum type, which means you can not create EnumSet of Month and DayOfWeek together.
  2. EnumSet doesn't allow null elements. Attempting to insert null on EnumSet will throw NullPointerException.
  3. EnumSet is not thread-safe, which means if it needs to be externally synchronized, when multiple threads access it and one of them modifies the collection.
  4. Iterator of EnumSet is fail-safe and weakly consistent, which means no ConcurrentModificationException. Also traversing order of Iterator is defined by natural ordering of Enum, and it may or may not show result of any modification done during iteration.
  5. EnumSet is a high performance Java Collection. It provides O(1) performance for add(), contains() and next() operations because of array based access. Preferably, use EnumSet over HashSet for storing Enum constants.

Thanks for your time guys, I hope you could take as much advantage of EnumSet as possible. You should also read Effective Java and its item on EnumSet to learn about the enum int pattern and how EnumSet is a good alternative to it. 

Javin Paul
Javin Paul

What do you think?

JAX Magazine - 2014 - 06 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions