java - 如何使用 EnumSet 将 2 位组合到单个字段中?

标签 java enums bit-manipulation enumset

给定一个用 1 个字节编码的二进制字符串,是否可以将该字节的多个位映射到枚举值?
例如:假设我想将我的领域切入以下:

  • 位 1 和位 2 = 字段 1
  • 位3 = 字段2
  • 位4 = 字段3
  • 位 5 = 字段 4
  • 其他位未使用

我怎样才能将其映射到:

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 语句。如果有人有更好的解决方案,我很乐意更改它;-)

谢谢!

最佳答案

不太确定你想要什么。这可能会令人感兴趣:

import java.util.*;
enum Field {
    field1((byte) 0xc0) {
        int filter_(byte mask) { // you may want this one to be different
            return mask & this.mask;
        }
    },
    field2((byte) 0x20), field3((byte) 0x10), field4((byte) 0x08);
    Field(byte mask) {
        this.mask = mask;
    }
    int filter_(byte mask) {
        return mask & this.mask;
    }
    static EnumSet<Field> filter(byte mask) {
        final EnumSet<Field> fields = EnumSet.noneOf(Field.class);
        for (Field field : values())
            if (field.filter_(mask) != 0) fields.add(field);
        return fields;
    }
    final byte mask;
}
public class Main {
    public static void main(String[] args) {
        for(Field field:Field.values()) {
            System.out.println(Field.filter(field.mask));
        }
    }
}

关于java - 如何使用 EnumSet 将 2 位组合到单个字段中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7335556/

相关文章:

java - Junit5 Mockito @InjecctMocks 不适用于 MockMvc

java - JPanel 位置被 BufferStrategy 重击

c# - 我应该为枚举成员使用什么 AttributeTarget?

java - 尝试在 Java 运行时从 Enum 获取关联值

java - 将数据显示到 RecyclerView 中

java - 如何使用 currentTimeMillis() 在类上运行计算速度?

java - 如何按包含的枚举对对象列表进行排序?

mysql - 优化 mysql 查询以在按位 where 子句上使用索引

c - 按位检查有符号乘法溢出会产生意外结果

c - 如何在不使用任何比较运算符且不使用 if、else 等的情况下以编程方式返回两个整数的最大值?