使用二元运算查明 int 是否包含枚举集中的元素
Find out if an int contains an element from an enum set using binary operations
我正在使用一个库,它通过对它们的值进行或运算来连接一个或多个枚举,如下所示:
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();
}
我需要提取组合生成 valueAsInt
的枚举,请记住:
- int 必须包含特殊枚举值之一 (0x00000000...0x00000030)
- int 可以包含零个或多个非特殊枚举值。
这是我所做的:
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("");
}
}
仅与掩码进行 ANDing 是不够的,因为它会 return TestEnum 值的正结果,VAL1 (0x00000001)
等
有更好的方法吗?
你的问题并没有说明只有一个特殊值;它指出那里 必须是一个 ,这是 至少一个 的另一种说法,所以不可能做你想做的,因为:
0x00000010 | 0x00000020 == 0x00000030
一旦 0x00000010
和 0x00000020
在集体 OR
值中累积,该值将与其中包含 0x00000030
的累积值无法区分。
但是,如果特殊值是 0x00000040
,一个简单的位掩码就可以了。
看来你的MASK_FOR_SPECIAL_ENUMS
必须等于0x000000F0
,不是0x000000FF
。
然后,在检查有效性后,您的查找方法需要循环遍历值 VAL1 到 VAL10,并收集匹配的值。
换句话说,是这样的:
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 );
}
我正在使用一个库,它通过对它们的值进行或运算来连接一个或多个枚举,如下所示:
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();
}
我需要提取组合生成 valueAsInt
的枚举,请记住:
- int 必须包含特殊枚举值之一 (0x00000000...0x00000030)
- int 可以包含零个或多个非特殊枚举值。
这是我所做的:
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("");
}
}
仅与掩码进行 ANDing 是不够的,因为它会 return TestEnum 值的正结果,VAL1 (0x00000001)
等
有更好的方法吗?
你的问题并没有说明只有一个特殊值;它指出那里 必须是一个 ,这是 至少一个 的另一种说法,所以不可能做你想做的,因为:
0x00000010 | 0x00000020 == 0x00000030
一旦 0x00000010
和 0x00000020
在集体 OR
值中累积,该值将与其中包含 0x00000030
的累积值无法区分。
但是,如果特殊值是 0x00000040
,一个简单的位掩码就可以了。
看来你的MASK_FOR_SPECIAL_ENUMS
必须等于0x000000F0
,不是0x000000FF
。
然后,在检查有效性后,您的查找方法需要循环遍历值 VAL1 到 VAL10,并收集匹配的值。
换句话说,是这样的:
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 );
}