5

I have an EnumSet and want to convert back-and-forth to/from an array of boolean primitives. If it works better, I could work with a List instead of an array, and/or Boolean objects rather than boolean primitives.

enum MyEnum { DOG, CAT, BIRD; }
EnumSet enumSet = EnumSet.of( MyEnum.DOG, MyEnum.CAT ); 

What I want to get on the other end is an array that looks like this:

[TRUE, TRUE, FALSE]

This Question here is similar to this one, Convert an EnumSet to an array of integers. Differences:

  • boolean or Boolean versus integers (obviously)
  • I want all members of the enum to be represented, with a TRUE for each enum element included in the EnumSet and a FALSE for each element that is excluded from the EnumSet. The other Question’s array includes only the items found in the EnumSet. (more importantly)
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154

3 Answers3

6

To do that you'd basically write

MyEnum[] values = MyEnum.values(); // or MyEnum.class.getEnumConstants()
boolean[] present = new boolean[values.length];
for (int i = 0; i < values.length; i++) {
  present[i] = enumSet.contains(values[i]);
}

Going the other direction, from boolean array present created above to enumSet_ created below.

EnumSet<MyEnum> enumSet_ = EnumSet.noneOf ( MyEnum.class );  // Instantiate an empty EnumSet.
MyEnum[] values_ = MyEnum.values ();
for ( int i = 0 ; i < values_.length ; i ++ ) {
    if ( present[ i ] ) {  // If the array element is TRUE, add the matching MyEnum item to the EnumSet. If FALSE, do nothing, effectively omitting the matching MyEnum item from the EnumSet.
        enumSet_.add ( values_[ i ] );
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Thanks. I was curious about the fancier lambda/streams syntax but it is good to show the simple-but-sure old-fashioned syntax. – Basil Bourque Jul 14 '16 at 07:09
  • I took the liberty of writing example code for going the other direction, from array to EnumSet. This code is based on some working code of mine, but modified to match your example here. So I'm not 100% if my code posted here is correct. – Basil Bourque Jul 14 '16 at 08:03
  • @BasilBourque, what is `QuarterHour`? – Andrew Tobilko Jul 14 '16 at 08:12
  • @AndrewTobilko Oops, that `QuarterHour` was a copy-paste carry-over error from [this Answer of mine](http://stackoverflow.com/a/38368468/642706) for another Question. Fixed now. – Basil Bourque Jul 14 '16 at 08:15
4

For the present, I don't see a better solution than

Boolean[] b = Arrays.stream(MyEnum.values()).map(set::contains).toArray(Boolean[]::new);

To get an EnumSet from an array of boolean primitives by using zip

MyEnum[] enums = zip(Arrays.stream(MyEnum.values()), Arrays.stream(b),
    (e, b) -> b ? e : null).filter(Objects::nonNull).toArray(MyEnum[]::new);
Community
  • 1
  • 1
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    The contains method won't iterate over the whole enum. The contains method is overridden in both of the EnumSet implementations, JumboEnumSet and RegularEnumSet. – D Levant Jul 14 '16 at 08:42
2

In Java 8 you could do it like this

List<Boolean> present = Arrays.stream(MyEnum.values()).map(enumSet::contains).collect(Collectors.toList());

To go the other way around you could do something like this

IntStream.range(0, present.size()).filter(present::get).mapToObj(i -> MyEnum.values()[i]).
    collect(Collectors.toCollection(() -> EnumSet.noneOf(MyEnum.class)));
D Levant
  • 116
  • 7