Ten minute tutorial

EnumSet in Java – RegularEnumSet vs JumboEnumSet

JavinPaul
java-duke

Javin Paul explains the usefulness of the Java special implementation, as well as examples and usecases

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. 

Author
Javin Paul is a Java programmer, blogger, working on Java, J2EE, UNIX, FIX Protocol. He shares Java tips on his blogs http://javarevisited.blogspot.com and http://java67.blogspot.com
Comments
comments powered by Disqus