Search code examples
javaenumsbinary-operators

Find out if an int contains an element from an enum set using binary operations


I am using a library that concatenates one or more enums by ORing their values like this:

    TestEnum {
        VAL1(0x00000001),
        VAL2(0x00000002),
        VAL3(0x00000100),
        VAL4(0x00000200),
        VAL5(0x00000400),
        VAL6(0x00000800),
        VAL7(0x00001000),
        VAL8(0x00002000),
        VAL9(0x00004000),
        VAL10(0x00008000),

        // special values
        VAL11(0x00000000),
        VAL12(0x00000010),
        VAL13(0x00000020),
        VAL14(0x00000030);

        private static final Map<Integer, TestEnum> TEST_ENUM_MAP;

        // constructor, populate map etc.

        public static TestEnum fromValue(final int value) {
            return TEST_ENUM_MAP.get(value);
        }
    }

    int valuesAsInt = 0;

    for (TestEnum testEnum : TestEnum.values()) {
        valuesAsInt |= testEnum.getValue();
    }

I need to extract the enums that were combined to produce valueAsInt keeping in mind that:

  • The int MUST contain one of the special enum values (0x00000000...0x00000030)
  • The int can contain zero or more of the non-special enum values.

This is what I did:

 private static final int MASK_FOR_SPECIAL_ENUMS = 0x000000FF;

 private static final ImmutableSet<TestEnum> SPECIAL_ENUMS = ImmutableSet.copyOf(Sets.newHashSet(TestEnum.VAL11, TestEnum.VAL12, TestEnum.VAL13, TestEnum.VAL14));

 private void lookupTestEnums(final int valueAsInt) {

      TestEnum testEnum = TestEnum.fromValue(valueAsInt & MASK_FOR_SPECIAL_ENUMS);
    if (testEnum == null || !SPECIAL_ENUMS.contains(testEnum)) {
        throw new ExceptionType("");
    }
 }

Just ANDing with the mask isn't sufficient because it'll return positive results for TestEnum values, VAL1 (0x00000001) etc.

Is there a better way of doing this?


Solution

  • It appears that your MASK_FOR_SPECIAL_ENUMS must be equal to 0x000000F0, not 0x000000FF.

    Then, after checking for validity, your lookup method needs to loop through values VAL1 through VAL10, and collect those that match.

    In other words, something like this:

    private static final int SPECIAL_MASK = 0x000000F0;
    
    int specialValue = valueAsInt & SPECIAL_MASK;
    int nonSpecialBits = valueAsInt & ~SPECIAL_MASK;
    for (TestEnum testEnum : TestEnum.values()) 
    {
        int value = testEnum.getValue();
        if( (value & SPECIAL_MASK) != 0 )
            continue; //this is one of the special values; ignore.
        if( (value & nonSpecialBits) == value )
            collection.add( testEnum );
    }