Getting value from EnumSet in Java

If you use EnumSet to store ordinary binary values ​​(1,2,4, etc.), then when the number of elements is less than 64, it seems to me that this is stored as a bit vector and it seems efficient for how long. There is an easy way to get the meaning of this long time. I want a quick and easy way to save the contents of a set in a file or database.

If I did it the old way, I would just use a long one and make a bit twisting myself, despite all the type problems, etc.

+6
java
source share
7 answers

As far as I know, this is not disclosed. You could basically rewrite it yourself - look at the EnumSet code to get an idea of ​​the code - but it is a pity that there is no better way to get to it: (

+6
source share

I do not think that this can be done in a general way. Converting to long is quite simple:

 public static <T extends Enum<T>> long enumSetToLong(EnumSet<T> set) { long r = 0; for(T value : set) { r |= 1L << value.ordinal(); } return r; } 

I do not know how you can convert from long back to EnumSet in general. There is no way (without reflection) that I know to get an array of enumeration values ​​to perform a search. You must do this based on enum.

I think serialization is the way to go. Simple serialization as a long time will be more susceptible to version errors or errors caused by permutation of constants in the enumeration.

+5
source share

As John Skeet mentioned, this information is not disclosed. But Dave Ray showed how easy it is to figure it out. I created a library that makes such conversions a lot easier. It also checks that in fact there are no more than 64 elements if you use "long". I had to create a new data type, but it can be used in the same way as BitSet or EnumSet. Please note that this requires Java 8 or later, as this uses interfaces with a default implementation.

Here's the link: http://claude-martin.ch/enumbitset/

Example:

  static enum MyEnum implements EnumBitSetHelper<MyEnum> { A, B, C } public static void main(final String[] args) { final EnumBitSet<MyEnum> set = EnumBitSet.of(MyEnum.A, MyEnum.C); long bitmask = set.toLong(); // = 3 } 
+2
source share

EnumSet implements Serializable , so you can just write it with an ObjectOutputStream .

+1
source share

if you add a parameter with an enumeration class, this is possible. An example that converts an enumeration to byte:

 public static <T extends Enum<T>, U extends Enum<?>> byte toByte(EnumSet<T> set, Class<U> type) { byte b = 0; if(type.getEnumConstants().length > 8) { throw new RuntimeException("enum set doesn't fit in one byte"); } for(Enum<?> e: type.getEnumConstants()) { if(set.contains(e)) { b |= 1 << e.ordinal(); } } return b; } public static <E extends Enum<E>> EnumSet<E> toSet(byte b, Class<E> type) { E[] enums = type.getEnumConstants(); EnumSet<E> enumSet = EnumSet.noneOf(type); for(int bit = 0; bit < 8; bit++) { if((b & 1 << bit) > 0) { enumSet.add(enums[bit]); } } return enumSet; } 
+1
source share

The EnumSet implementation (typical - this is optional) uses the ordinal values ​​of the enum values. You should not assume that ordinals will always remain the same. So, if you want to efficiently store enum arrays using ordinals, you must also save the map from the enumeration name to a serial number (probably saved as a sequence of enumeration names).

EnumSet itself does not have a large serialized form. It just unloads from the listings. The body of which will be transcribed into a series of whole references to objects, and not a bit.

0
source share

BitSet can be useful in this situation because it provides conversion to / from an array of bytes. You may need to declare an enum with explicit values ​​(1,2,3 ..) for BitSet indeces. Unlike a long one, which is always 64-bit, BitSet does not seem to be able to limit its length (for example, 64 bits).

0
source share

All Articles