title: Store an ordering of Enums in Java
body: <p>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.</p>
  
  <p>Currently I am storing the Order as Guava <a href="https://google.github.io/guava/releases/23.0/api/docs/com/google/common/collect/ImmutableSet.html" rel="nofollow noreferrer"><code>ImmutableSet</code></a>, because that guarantees to retain insertion order. However, I have used <a href="http://javaspecialists.co.za/archive/Issue029.html" rel="nofollow noreferrer" title="Determining Memory Usage in Java">the methods explained on this page</a> to compare memory usage in an <code>EnumSet&lt;Flag&gt;</code>, an <code>ImmutableSet&lt;Flag&gt;</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:</p>
  
  <blockquote>
    <p>EnumSet: 32 bytes<br>
    ImmutableSet: 832 bytes<br>
    Array: 272 bytes</p>
  </blockquote>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Update:</p>
  
  <p>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 (<a href="http://code.google.com/p/guava-libraries/issues/detail?id=1022" rel="nofollow noreferrer" title="ImmutableList&lt;E&gt; enumUniverse()">see here for a discussion of this problem</a>), but here goes:</p>
  
  <pre><code>public class EnumOrdering&lt;E extends Enum&lt;E&gt;&gt; implements Iterable&lt;E&gt; {
      private final Class&lt;E&gt; type;
      private final byte[] order;
  
      public EnumOrdering(final Class&lt;E&gt; type, final Collection&lt;E&gt; 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&lt;E&gt; iterator() {
          return new AbstractIterator&lt;E&gt;() {
              private int offset = -1;
              private final E[] enumConstants = type.getEnumConstants();
  
              @Override
              protected E computeNext() {
                  if (offset &lt; order.length - 1) {
                      return enumConstants[order[++offset]];
                  }
                  return endOfData();
              }
          };
      }
  }
  </code></pre>
  
  <p>The memory footprint is:</p>
  
  <blockquote>
    <p>EnumOrdering:104</p>
  </blockquote>
  
  <p>That's a pretty good result so far, thanks to bestsss and JB Nizet!</p>
  
  <p>Update: I have changed the code to only implement Iterable, because anything else would require sensible implementations for equals / hashCode / contains etc.</p>