Store an ordering of Enums in Java

sgsd

New Member
In java, an EnumSet stores the items it contains in a bitmask / bit vector using a \[code\]long\[/code\] (\[code\]RegularEnumSet\[/code\]) or \[code\]long[]\[/code\] (\[code\]JumboEnumSet\[/code\]). I have now come across a use case where I have many thousand domain Objects (let's call them \[code\]Node\[/code\]), each of which will show all items of an enum (let's call that \[code\]Flag\[/code\]) in an order that will vary per Object.Currently I am storing the Order as Guava \[code\]ImmutableSet\[/code\], because that guarantees to retain insertion order. However, I have used the methods explained on this page to compare memory usage in an \[code\]EnumSet<Flag>\[/code\], an \[code\]ImmutableSet<Flag>\[/code\] and a \[code\]Flag[]\[/code\]. Here are the results when a) Flag has 64 enum items and b) all three variants contain all 64 items:\[quote\] EnumSet: 32 bytes
ImmutableSet: 832 bytes
Array: 272 bytes\[/quote\]So my question is: is there a clever way to pack the enum ordering into a numeric value to get a memory footprint smaller than that of the array? If it makes a difference: in my use case I would assume that the ordering always contains all Enum items.To clarify: my enum is much smaller than that and I don't have any memory problems as of now, nor is it likely that this situation will ever give me memory problems. It's just that this inefficiency bugs me, even on this microscopic level.Update:After suggestions from the various answers and comments I came up with this data structure that uses a byte array. Caveat: It doesn't implement the Set interface (doesn't check for unique values) and it won't scale to large enums beyond what a byte can hold. Also, the complexity is pretty awful, because Enum.values() has to be queried repeatedly (see here for a discussion of this problem), but here goes:\[code\]public class EnumOrdering<E extends Enum<E>> implements Iterable<E> { private final Class<E> type; private final byte[] order; public EnumOrdering(final Class<E> type, final Collection<E> order) { this.type = type; this.order = new byte[order.size()]; int offset = 0; for (final E item : order) { this.order[offset++] = (byte) item.ordinal(); } } @Override public Iterator<E> iterator() { return new AbstractIterator<E>() { private int offset = -1; private final E[] enumConstants = type.getEnumConstants(); @Override protected E computeNext() { if (offset < order.length - 1) { return enumConstants[order[++offset]]; } return endOfData(); } }; }}\[/code\]The memory footprint is:\[quote\] EnumOrdering:104\[/quote\]That's a pretty good result so far, thanks to bestsss and JB Nizet!Update: I have changed the code to only implement Iterable, because anything else would require sensible implementations for equals / hashCode / contains etc.
 
Back
Top