If the elements of an enumerated type are used primarily in sets, it is traditional to use the
// Bit field enumeration constants - OBSOLETE!
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
// Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles) { ... }
}
This representation lets you use the bitwise
text.applyStyles(STYLE_BOLD | STYLE_ITALIC);
But internally, each
// EnumSet - a modern replacement for bit fields
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
// Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles) { ... }
}
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
In summary, just because an enumerated type will be used in sets, there is no reason to represent it with bit fields. The
int
enum pattern (Item 34), assigning a different power of 2 to each constant:// Bit field enumeration constants - OBSOLETE!
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
// Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles) { ... }
}
This representation lets you use the bitwise
OR
operation to combine several constants into a set, known as a bit field:text.applyStyles(STYLE_BOLD | STYLE_ITALIC);
But internally, each
EnumSet
is represented as a bit vector. If the underlying enum type has sixty-four or fewer elements—and most do—the entire EnumSet
is represented with a single long
, so its performance is comparable to that of a bit field. Bulk operations, such as removeAll
and retainAll
, are implemented using bitwise arithmetic, just as you’d do manually for bit fields.// EnumSet - a modern replacement for bit fields
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
// Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles) { ... }
}
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
In summary, just because an enumerated type will be used in sets, there is no reason to represent it with bit fields. The
EnumSet
class combines the conciseness and performance of bit fields with all the many advantages of enum types described in Item 34. The one real disadvantage of EnumSet
is that it is not, as of Java 9, possible to create an immutable EnumSet
, but this will likely be remedied in an upcoming release. In the meantime, you can wrap an EnumSet
with Collections.unmodifiableSet
, but conciseness and performance will suffer.
No comments:
Post a Comment