如何使用 EnumSet 将 2 位组合到单个字段中?
给定一个在 1 个字节上编码的二进制字符串,是否可以将该字节的几个位映射到一个枚举值?
例如:假设我想将我的字段切成这样:
- bit1和bit2 = field1
- bit3 = field2
- bit4 = field3
- bit5 = field4
- 其他位未使用
我如何将其映射到,比如说:
public enum MyEnum {
FIELD1, FIELD2, FIELD3, FIELD4;
private static final EnumSet<MyEnum> ALLFIELDS = EnumSet.allOf(MyEnum.class);
}
我想做的是过滤掉这些枚举值使用位掩码。为此,我执行了以下方法:
public static <E extends Enum<E>> EnumSet<E> filterWithBitMask(EnumSet<E> set, int bitmask) {
List<E> kept = new ArrayList<E>();
for (E property : set) {
if ((bitmask & (1 << ((Enum<E>) property).ordinal())) != 0) {
kept.add(property);
}
}
EnumSet<E> selectedProperties = set.clone();
selectedProperties.retainAll(kept);
return selectedProperties;
}
只要我的枚举字段代表单个位,这种方法就可以正常工作,但我不知道如何将它们组合成单个字段。抱歉,如果这看起来很明显,但这是我第一次在位级别操作数据......
编辑评论: 我编辑了字段结构以代表我真正拥有的内容。因此,唯一跨度超过 1 位的字段是 field1。根据 bit1 和 bit2 的存在,我为 field1 分配一个权重变量。
public enum MyByte {
BIT_1, BIT_2, BIT_3, BIT_4, BIT_5;
private static final EnumSet<MyByte> ALLPROPERTIES = EnumSet.allOf(MyByte.class);
public static EnumSet<Fields> getValues(int bitmask) {
EnumSet<MyByte> selectedBits = filterWithBitMask(ALLPROPERTIES, bitmask);
int weight = 0;
EnumSet<Fields> fields = null;
if (selectedBits.contains(BIT_1))
weight += 1;
if (selectedBits.contains(BIT_2))
weight += 2;
if (selectedBits.contains(BIT_1) || selectedBits.contains(BIT_2))
fields = EnumSet.of(Fields.FIELD1.setValue(weight));
if (selectedBits.contains(BIT_3)) {
if (fields != null)
fields.add(Fields.FIELD2);
else fields = EnumSet.of(Fields.FIELD2);
}
if (selectedBits.contains(BIT_4)) {
if (fields != null)
fields.add(Fields.FIELD3);
else fields = EnumSet.of(Fields.FIELD3);
}
if (selectedBits.contains(BIT_5)) {
if (fields != null)
fields.add(Fields.FIELD4);
else fields = EnumSet.of(Fields.FIELD4);
}
return fields;
}
public enum Fields {
// BIT_1 and BIT_2
FIELD1,
// BIT_3
FIELD2,
// BIT_4
FIELD3,
// BIT_5
FIELD4;
private int value;
public Fields setValue(int i) {
this.value = i;
return this;
}
}
}
这是我现在想出的肮脏的解决方案,但我不太喜欢所有这些 if 语句。如果有人有更好的解决方案,我很乐意更改它;-)
谢谢!
Given a binary string coded on 1 byte, is it possible to map several of that byte's bits into an enum value ?
e.g. : suppose I want to cut my field into this :
- bit1 and bit2 = field1
- bit3 = field2
- bit4 = field3
- bit5 = field4
- other bits are unused
How could I map that to, say :
public enum MyEnum {
FIELD1, FIELD2, FIELD3, FIELD4;
private static final EnumSet<MyEnum> ALLFIELDS = EnumSet.allOf(MyEnum.class);
}
What I'm trying to do is to filter out these enum values using a bitmask. For that, I did the following method :
public static <E extends Enum<E>> EnumSet<E> filterWithBitMask(EnumSet<E> set, int bitmask) {
List<E> kept = new ArrayList<E>();
for (E property : set) {
if ((bitmask & (1 << ((Enum<E>) property).ordinal())) != 0) {
kept.add(property);
}
}
EnumSet<E> selectedProperties = set.clone();
selectedProperties.retainAll(kept);
return selectedProperties;
}
This works fine as long as my enum fields represent a single bit, but I can't figure out how to combine them into a single field. Sorry if that looks obvious, but this is the first time I'm manipulating data at the bit level...
EDIT COMMENTS :
I edited the field structure to represent what I really have. So the only field that spans more than 1 bit is field1. Based on the presence of bit1 and bit2, I assign an weight variable to field1.
public enum MyByte {
BIT_1, BIT_2, BIT_3, BIT_4, BIT_5;
private static final EnumSet<MyByte> ALLPROPERTIES = EnumSet.allOf(MyByte.class);
public static EnumSet<Fields> getValues(int bitmask) {
EnumSet<MyByte> selectedBits = filterWithBitMask(ALLPROPERTIES, bitmask);
int weight = 0;
EnumSet<Fields> fields = null;
if (selectedBits.contains(BIT_1))
weight += 1;
if (selectedBits.contains(BIT_2))
weight += 2;
if (selectedBits.contains(BIT_1) || selectedBits.contains(BIT_2))
fields = EnumSet.of(Fields.FIELD1.setValue(weight));
if (selectedBits.contains(BIT_3)) {
if (fields != null)
fields.add(Fields.FIELD2);
else fields = EnumSet.of(Fields.FIELD2);
}
if (selectedBits.contains(BIT_4)) {
if (fields != null)
fields.add(Fields.FIELD3);
else fields = EnumSet.of(Fields.FIELD3);
}
if (selectedBits.contains(BIT_5)) {
if (fields != null)
fields.add(Fields.FIELD4);
else fields = EnumSet.of(Fields.FIELD4);
}
return fields;
}
public enum Fields {
// BIT_1 and BIT_2
FIELD1,
// BIT_3
FIELD2,
// BIT_4
FIELD3,
// BIT_5
FIELD4;
private int value;
public Fields setValue(int i) {
this.value = i;
return this;
}
}
}
Here is the dirty solution I came up with for now, but I don't really like it with all those if statements. If someone has a better solution, I'd be glad to change this ;-)
Thanks !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不太确定你想要什么。这可能会令人感兴趣:
not quite sure what you want. this might be of interest: