Wednesday, August 20, 2008

Java's EnumSet - fun for the whole family!

In the dark, rarely visited corners of Java lies a rather powerful, often overlooked tool - the EnumSet. When Java finally got enums in Java 5, there was enough celebration to overlook this useful little construct.
An EnumSet provides a quick and easy way to stuff many enum'ed values into one variable and pass it around. Some surprisingly good static syntatic sugar makes creating EnumSets very easy.
Where EnumSets come in particularly handy is eradicating that ugly vestige of C code, the bit-stuffed integer value. I recently came across some new code that still uses named constants in order to work around a custom data serialization issue, and while I can't fix that data serialization weakness, I can hide it while adding type safety to the code via an EnumSet.
How about a short, informative, correct example:

import java.util.EnumSet;

public class TestingEnumSet {

enum Simpsons { Homer, Marge, Lisa, Bart, Maggie };
public static void main(String[] args) {
EnumSet<Simpsons> parents = EnumSet.of(Simpsons.Homer, Simpsons.Marge);

// Uses the order of defined enum to determine range inclusion
EnumSet<Simpsons> kids = EnumSet.range(Simpsons.Lisa, Simpsons.Maggie);

EnumSet<Simpsons> parents2 = EnumSet.complementOf(kids);

EnumSet<Simpsons> everybody = EnumSet.allOf(Simpsons.class);

// Look Ma, no if(simpsons & HOMER_FLAG != 0) Yay!
if(parents.contains(Simpsons.Homer))
System.out.println("Homer is present");

if(parents.contains(Simpsons.Bart))
System.out.println("D'oh!");

System.out.println("The kids...");
for(Simpsons s : kids)
System.out.println(s);

System.out.println("Go to Moe's bar? " +
canGoToMoes(EnumSet.of( Simpsons.Homer,
Simpsons.Marge,
Simpsons.Bart)));
}

public static boolean canGoToMoes(EnumSet<Simpsons> atDoor) {
return !atDoor.contains( EnumSet.range(Simpsons.Lisa, Simpsons.Maggie) );
}
}

Learning new things is fun.

2 snarky replies:

Lukáš Vlček said...

Cool. I was looking for short tutorial like this. Thanks!

Stefan said...

The canGoToMoes method does not work correctly since the atDoor.contains is only matching one item and not for a range.