位运算 与(&) 或(|) 异或(^)
//按位与&(都1则结果才为1)
0&0=0; 0&1=0; 1&0=0; 1&1=1;
//按位或|(有一个为1则结果就为1)
0|0=0; 0|1=1; 1|0=1; 1|1=1;
//按位异或^(异则结果为1)
0^0=0; 0^1=1; 1^0=1; 1^1=0;
位运算 多选字段
IM(1, "IM消息"),
SYSTEM(2, "系统提醒"),
MAIL(3, "邮箱"),
SMS(4, "短信");
但在数据查询时,我们需要对字符串进行分隔。并且字符串类型的字段在查询效率和存储空间上不如整型字段。因此,我们可以用“位”来解决这个问题。我们采取不同的位来分别表示不同类别的标识字段。
因此,当某个任务支持 IM 时,则保存 1(0000 0001);支持系统消息时,则保存 2(0000 0010),支持邮箱时,则保存 4(0000 0100);支持短信时,则保存 8(0000 1000)。四种都支持,则保存 15 (0000 11111)。
位 | 值 | 说明 |
---|---|---|
00000001 | 1 | 支持IM |
00000010 | 2 | 支持系统消息 |
00000011 | 3 | 支持IM、系统消息 |
00000100 | 4 | 支持邮箱 |
00000101 | 5 | 支持邮箱、IM |
00000110 | 6 | 支持邮箱、系统消息 |
00000111 | 7 | 支持邮箱、IM、系统消息 |
00001000 | 8 | 支持短信 |
... | ||
00001111 | 15 | 支持邮箱、IM、系统消息、短信 |
紧接着,我们通过封装常用方法来实现增删改。
/**
* 判断
* @param mod 用户当前值
* @param value 需要判断值
* @return 是否存在
*/
public static boolean hasMark(long mod, long value) {
return (mod & value) == value;
}
/**
* 增加
* @param mod 已有值
* @param value 需要添加值
* @return 新的状态值
*/
public static long addMark(long mod, long value) {
if (hasMark(mod, value)) {
return mod;
}
return (mod | value);
}
/**
* 删除
* @param mod 已有值
* @param value 需要删除值
* @return 新值
*/
public static long removeMark(long mod, long value) {
if (!hasMark(mod, value)) {
return mod;
}
return mod ^ value;
}
总结一下,我们在数据库设计时,将多个标识字段合并成一个字段,并把这个字段改成字符串型方式保存,不仅消除相同字段的冗余,而且当增加新的渠道类别时,不需增加新的字段,但是字符串类型的字段在查询效率和存储空间上不如整型字段。因此,我们可以参考用“位”来解决这个问题。我们采取不同的位来分别表示不同类别的标识字段。