Java EnumSet - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Saturday, February 4, 2017

Java EnumSet

EnumSet is one of the specialized implementation of set interface for use with enum types, introduced in Java 1.5 with enumeration type. Programmer often use HashSet or ArrayList to store enum type, because they are unaware about this little gem. I was not aware about this class until I come across one of the corporate project was using it. Since Enum constants are unique and have predefined length, you can't create new enum at runtime. It allows java designer to make highly optimized EmumSet.

All of the elements of the enum set must come from single enum that is specified, explicitly or implicitly when the set is created. Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of thi class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags." Even bulk operations (such as containsAll and retainAll) should run very quickly if their argument is also an enum set.

EnumSet extends AbstractSet and implements Set. It is specifically for use with elements of an enum type.

EnumSet is a generic class that has this declaration:

public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable

Here, E specifies the elements. Notice that E must extend Enum<E>, which enforces the requirement that the elements must be of the specified enum type.

Java EnumSet constructors

EnumSet defines no constructors. Instead, it uses the factory methods to create objects. All methods can throw NullPointerException. The copyOf( ) and range( ) methods can also throw IllegalArgumentException.

Java EnumSet methods

Method Description
public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) Creates an enum set containing all of the elements in the specified element type.
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) Creates an empty enum set with the specified element type.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> copyOf(EnumSet<E> s) Creates an enum set with the same element type as the specified enum set, initially containing the same elements (if any).
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> copyOf(Collection<E> c) Creates an enum set initialized from the specified collection. If the specified collection is an EnumSet instance, this static factory method behaves identically to {@link #copyOf(EnumSet)}. Otherwise, the specified collection must contain at least one element (in order to determine the new enum set's element type).
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> complementOf(EnumSet<E> s) Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E e) Creates an enum set initially containing the specified element.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E e1, E e2) Creates an enum set initially containing the specified elements e1 through e2.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E e1, E e2, E e3) Creates an enum set initially containing the specified elements e1 through e3.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E e1, E e2, E e3, E e4) Creates an enum set initially containing the specified elements e1 through e4.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) Creates an enum set initially containing the specified elements e1 through e5.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> of(E first, E... rest) Creates an EnumSet that contains first and zero or more additional enumeration values.
public static <E extends Enum<E>> EnumSet<E> EnumSet<E> range(E from, E to)
public EnumSet<E> clone() Returns a copy of this set.

Note As per Oracle documentation:

Overloading of this of() method exist to initialize an enum set with one through five elements. A sixth overloading is provided that uses the varargs feature. This overloading may be used to create an enum set initially containing an arbitrary number of elements, but is likely to run slower than the overloading that do not use varargs.

EnumSet Example in Java

In this example, we have used basic colours RED, GREEN and BLUE to create a custom colour by using EnumSet. EnumSet is very good for combining effects, whether it's text styles e.g. BOLD and UNDERLINE, or combining basic colours to create custom color here.

package com.walking.techie;

import java.util.EnumSet;

/**
 * Simple Java Program to demonstrate how to use EnumSet.
 * Using Enum with EnumSet will give you far better performance
 * than using Enum with HashSet or LinkedHashSet.
 *
 * @Author walkingtechie
 */
public class EnumSetColorDemo {

  private enum Color {
    RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255);
    private int red;
    private int green;
    private int blue;

    Color(int red, int green, int blue) {
      this.red = red;
      this.green = green;
      this.blue = blue;
    }
  }

  public static void main(String[] args) {
    // RED + GREEN = YELLOW
    EnumSet<Color> yellow = EnumSet.of(Color.RED, Color.GREEN);
    // RED + GREEN + BLUE = WHITE
    EnumSet<Color> white = EnumSet.of(Color.RED, Color.GREEN, Color.BLUE);
    // REN + BLUE = PINK
    EnumSet<Color> pink = EnumSet.of(Color.RED, Color.BLUE);

    drawLine(yellow);
    drawLine(white);
    drawLine(pink);

  }

  private static void drawLine(EnumSet<Color> colors) {
    System.out.println("Colors to draw line : " + colors);
    for (Color color : colors) {
      System.out.println("Drawing line in color : " + color);
    }
  }
}

Output of above program is shown below:

Colors to draw line : [RED, GREEN]
Drawing line in color : RED
Drawing line in color : GREEN
Colors to draw line : [RED, GREEN, BLUE]
Drawing line in color : RED
Drawing line in color : GREEN
Drawing line in color : BLUE
Colors to draw line : [RED, BLUE]
Drawing line in color : RED
Drawing line in color : BLUE

Important point of Java EnumSet

  • EnumSet is a special set implementation, only application to Java Enum , you can store instances of the single enum type. Adding instance of other enum type will result compile time error, as Java Enum provide type-safety.
  • EnumSets are represented internally as bit vectors. This representation is extremely compact and efficient.
  • The space and time performance of Java EnumSet class allow to use as a high-quality, type-safe alternative to tradition int based "int flags".
  • The iterator returned by the iterator method traverses the elements in their natural order i.e the order in which the enum constants are declared.
  • The returned iterator is weakly consistent: it will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.
  • EnumSet does not permit null elements. Attempts to insert a null element will throw NullPointerException.
  • EnumSet is not synchronized like most of the other collection implementations. Though if you need, you can synchronized by using the Collections.synchronizedSet method. You can do like:
    Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
  • All the basic operations of EnumSet execute in constant time.
  • Java EnumSet much likely (though not guaranteed) to be much faster than their HashSet counterparts.
  • Java EnumSet is an abstract class, so you can not create an instance using new keyword. That's why EnumSet provides several static factory methods for creating instance.

More Example of Java EnumSet

Java EnumSet.allOf(Class<E> elementType)

In the following code shows how to use EnumSet.allOf(Class<E> elementType) method.

package com.walking.techie;


import java.util.EnumSet;

public class EnumSetAllOfDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    // create set using all elements of Days
    EnumSet<Days> days = EnumSet.allOf(Days.class);
    System.out.println(days);
  }
}

Output of above program is shown below:

[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]

Java EnumSet.clone()

In the following code shows how to use EnumSet.clone() method.

package com.walking.techie;

import java.util.EnumSet;

public class EnumSetCloneDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    // create set using all elements of Days
    EnumSet<Days> days = EnumSet.allOf(Days.class);
    System.out.println("Original EnumSet : " + days);
    EnumSet<Days> copiedDays = days.clone();
    System.out.println("Copied EnumSet : " + copiedDays);
  }
}

Output of above program is shown below:

Original EnumSet : [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
Copied EnumSet : [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]

Java EnumSet.complementOf(EnumSet<E> s)

In the following code shows how to use EnumSet.complementOf(EnumSet<E> s) method.

package com.walking.techie;

import java.util.EnumSet;

public class EnumSetComplementOfDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    // create set using elements of Days
    EnumSet<Days> twoDays = EnumSet.of(Days.MONDAY, Days.TUESDAY);
    System.out.println("First two days of EnumSet : " + twoDays);

    EnumSet<Days> restDays = EnumSet.complementOf(twoDays);
    System.out.println("Last five days of EnumSet : " + restDays);
  }
}

Output of above program is shown below:

First two days of EnumSet : [MONDAY, TUESDAY]
Last five days of EnumSet : [WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]

Java EnumSet.copyOf(Collection<E> c)

In the following code shows how to use EnumSet.copyOf(Collection<E> c) method.

package com.walking.techie;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class EnumSetCollectionCopyOfDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    // create a collection
    List<Days> collection = new ArrayList<>();
    collection.add(Days.MONDAY);
    collection.add(Days.TUESDAY);
    collection.add(Days.WEDNESDAY);
    System.out.println("Days in list : " + collection);

    //create an enum set from a copy of collection
    EnumSet<Days> someDays = EnumSet.copyOf(collection);
    System.out.println("Days in enum set : " + someDays);
  }
}
Days in list : [MONDAY, TUESDAY, WEDNESDAY]
Days in enum set : [MONDAY, TUESDAY, WEDNESDAY]

Java EnumSet.copyOf(EnumSet<E> s)

In the following code shows how to use EnumSet.copyOf(EnumSet<E> s) method.

package com.walking.techie;

import java.util.EnumSet;

public class EnumSetCopyOfDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    EnumSet<Days> days = EnumSet.allOf(Days.class);

    System.out.println("Days of enum set : " + days);

    // create a second set which is a copy of set days
    EnumSet<Days> copiedDays = EnumSet.copyOf(days);

    System.out.println("Days of copied enum set : " + copiedDays);
  }
}

Output of above program is shown below:

Days of enum set : [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
Days of copied enum set : [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]

Java EnumSet.noneOf(Class<E> elementType)

In the following code shows how to use EnumSet.noneOf(Class<E> elementType) method.

package com.walking.techie;

import java.util.EnumSet;

public class EnumSetNoneOfDemo {

  private enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
  }

  public static void main(String[] args) {
    EnumSet<Days> days = EnumSet.allOf(Days.class);

    System.out.println("Days of enum set : " + days);

    // create empty enum set type of Days
    EnumSet<Days> emptyDays = EnumSet.noneOf(Days.class);

    System.out.println("Empty enum set : " + emptyDays);
  }
}

Output of above program is shown below:

Days of enum set : [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
Empty enum set : []

No comments :

Post a Comment