Java 使用位屏蔽将启用应用程序的功能存储到数据库中

Java 使用位屏蔽将启用应用程序的功能存储到数据库中,java,Java,我想将许多应用程序功能存储到数据库中。我想使用一个表行来实现这一点,所以我想使用位屏蔽来存储启用的功能。我试过这个: HashMap<String, Integer> map = new HashMap<String, Integer>(); int database_value = 0; public int setFeatureBitmask(int value) { int bitmask = 0; bitmask |= value;

我想将许多应用程序功能存储到数据库中。我想使用一个表行来实现这一点,所以我想使用位屏蔽来存储启用的功能。我试过这个:

HashMap<String, Integer> map = new HashMap<String, Integer>();
int database_value = 0; 

public int setFeatureBitmask(int value) {
    int bitmask = 0;
    bitmask |= value;       
    return bitmask;
}

public static Set<String> processFeature(Integer bitmask) {
    HashMap<String, Integer> newMap = new HashMap<String, Integer>();

    return newMap.entrySet().stream().filter(e -> (e.getValue() & bitmask) == e.getValue()).map(e -> e.getKey())
            .collect(Collectors.toSet());
}

@BeforeAll
public void setupData() {
    System.out.println("Populating settings map");

    map.put("Type1", 1);
    map.put("Type2", 2);
    map.put("Type3", 4);
    map.put("Type4", 8);
    map.put("Type5", 16);
    map.put("Type6", 32);
    map.put("Type7", 64);
    map.put("Type8", 128);
    map.put("Type9", 256);
    map.put("Type10", 512);
    map.put("Type11", 1024);
    map.put("Type12", 2048);
    map.put("Type13", 4096);
    map.put("Type14", 8192);
    map.put("Type15", 16384);
    map.put("Type16", 32768);
    map.put("Type17", 65536);
    map.put("Type18", 131072);
    map.put("Type19", 262144);
}

@Test
public void writeData() {
    System.out.println("Converting Map using bitmasking");

    for(int i=0; i<map.size(); i++) {

        int number_value = map.get(i);                      
        int result = setFeatureBitmask(number_value);           
        database_value = database_value + result;
    }       
}

@AfterAll
public void databaseInsert() {
    System.out.println("Final resut to insert into Database " + database_value);

    System.out.println("Converting back values from database");

    // read here values from database_value variable and convert them into hash     
}

但是对于toMap,我得到了方法toMap f->{},f->{},v1,v2->{},LinkedHashMap::new对于类型DatabaseFeaturesTest是未定义的,我不喜欢使用随机常数来表示特性

首先将要素包装到枚举:

public enum Feature {
     A("Type1", 1), // 1 << 0
     B("Type2", 2), // 1 << 1
     C("Type3", 4), // 1 << 2,
     ...
     F("Type6", 32); // 1 << 5

     private final String featureName;
     private final int value;

     // Constructor, getters/setters
}
要禁用功能,请执行以下操作:

public void enableFeature(Feature feature) {
    opts = opts | feature.getValue(); // Or regular sum
}
public void disableFeature(Feature feature) {
    opts = opts & (~feature.getValues());
}
要测试功能是否已启用,请执行以下操作:

public boolean isFeatureEnabled(Feature feature) {
    return (opts & feature.getValue()) != 0;
}
要将地图要素转换为组合整数,请执行以下操作:

int opts = features.entrySet().stream().filter(Entry::getValue)
                   .mapToInt(e -> e.getKey().getValue())
                   .sum();
现在,您将OPT作为常规整数存储到数据库中

重读:

final int optsFromDatabase = ....; // Read that combination value from DB

Map<Feature, Boolean> featureMaps = 
       Arrays.stream(Feature.values())
             .collect(toMap(f -> f, 
                            f -> (optsFromDatabase & f.getValue()) != 0,
                            (v1, v2) -> v2,
                            LinkedHashMap::new));
更新

要支持许多功能,例如~100个功能,您应该坚持使用字符串

现在,您应该修改要素类abit:

public enum Feature {
     A("Type1", 0), // index 0 in bit string
     B("Type2", 1), // index 1 in bit String
     C("Type3", 2), // index 2 in bit String
     ...
     Z("TypeZ", 100); // index 100 in bit String

     private final String featureName;
     private final int index;
}
现在将地图转换为位字符串:

public String convertToDatabaseValue() {
    return Arrays.stream(Feature.values()).map(f -> isFeatureEnabled(f) ? "1" : "0").collect(joining());
}

public Map<Feature, Boolean> initFromDatabaseValue(String bitString) {
    // Note that, bitString length should equals to your number of feature. Or you have to padding it
    char[] bitArray = bitString.toCharArray();
    return Arrays.stream(Feature.values())
            .collect(toMap(f -> f,
                    f -> bitArray[f.getIndex()] == '1',
                    (v1, v2) -> v2,
                    LinkedHashMap::new));
}

我不确定你的问题/困惑集中在这里。位掩码只是一个数字,但它被解释为一系列位。要回答Java或SQL中的位掩码问题,您只需要使用位运算符,就像您在代码中所做的那样。也许您可以向我们展示您建议的SQL表结构。@TimBiegeleisen我的目标是只使用一个数字,例如15990793,以了解是否启用了某些功能。为此,我想使用位运算符。@PeterPenzov,位字段可以通过简单的相加组合成一个数字,与使用或位运算符相同。然后,为了测试一个特定位的数字,您只需使用该数字,例如0x06&0x02==0x02这就是@TimBiegeleisen告诉您的,一个数字表示N个位数,其中N=bytes*8,您只需使用逐位运算符屏蔽您不关心的位。我想你需要仔细研究一下掩蔽到底是什么,单字节无符号整数0-255表示8位,您需要返回并澄清您的问题所在,因为问题不清楚,因为很明显您在问题和注释中混淆了术语和概念。我可以再问一个问题如何进行值验证吗?
public enum Feature {
     A("Type1", 0), // index 0 in bit string
     B("Type2", 1), // index 1 in bit String
     C("Type3", 2), // index 2 in bit String
     ...
     Z("TypeZ", 100); // index 100 in bit String

     private final String featureName;
     private final int index;
}
public String convertToDatabaseValue() {
    return Arrays.stream(Feature.values()).map(f -> isFeatureEnabled(f) ? "1" : "0").collect(joining());
}

public Map<Feature, Boolean> initFromDatabaseValue(String bitString) {
    // Note that, bitString length should equals to your number of feature. Or you have to padding it
    char[] bitArray = bitString.toCharArray();
    return Arrays.stream(Feature.values())
            .collect(toMap(f -> f,
                    f -> bitArray[f.getIndex()] == '1',
                    (v1, v2) -> v2,
                    LinkedHashMap::new));
}