宁夏水利厅建设管理处网站,展馆公司,高新网站设计找哪家,做网站反应快的笔记本有哪些通过位运算打多个标记 如何在一个字段上#xff0c;记录多个标记#xff1f; 如何在一个字段上#xff0c;记录不同类型的多个标记#xff1f; 如何用较少的字段#xff0c;记录多个标记#xff1f; 如何在不增加字段的要求下#xff0c;记录新增的标记#xff1f; 在实…通过位运算打多个标记 如何在一个字段上记录多个标记 如何在一个字段上记录不同类型的多个标记 如何用较少的字段记录多个标记 如何在不增加字段的要求下记录新增的标记 在实际的开发中经常有这样的需求需要用尽可能少的字段记录多个标记
比如交易中一个订单是否发生过支付是否进行过发货是否发生过退货退款是否进行过理赔
比如社交中一个帖子是否审核通过是否被举报过是否发生过二次编辑是否要置顶等等
以上场景最终都是要记录到数据库中的。如果每增加一个类型都增加一个字段标记是或者否的话那每行记录的字段数得增加到多少
所以我们的诉求是希望通过尽可能少的字段最好是不要增加数据库的字段能够记录同时记录多个标记。
这样的场景一种解决方式是在数据库中增加一个内容是JSON格式的字段然后每次往JSON中增加内容。这种方式的好处是比较灵活增加标记不用修改数据库DDL。而且不需要记录的标记可以不存储不用占用存储空间。但文本格式毕竟会占用较多的存储空间随着标记的增加类似MySQL数据库可能需要调整字符串长度
另一种解决方式是位运算通过在不同的位置填充0或者1表示标记的是或者否有或者没有。大名鼎鼎的布隆过滤器实现原理也是类似的
比如说一个订单我们需要记录它是否发生过支付是否发生过发货是否发生过退货那么就可以设计这么几个标记
PAY_FLAG(1L 1L),
DELIVER_FLAG(1L 2L),
REFUNR_FLAG(1L 3L),然后在订单表中增加一个flag字段通过位运算记录订单的不同标记。方法如下
// 设置Flag
public static Long setFlag(Long orderFlag, OrderFlagEnum orderFlagEnum) {orderFlag | orderFlagEnum.getFlag();return orderFlag;
}
// 清除Flag
public static Long clearFlag(Long orderFlag, OrderFlagEnum orderFlagEnum) {orderFlag ~orderFlagEnum.getFlag();return orderFlag;
}// 判断是否设置过某个Flag
public static boolean hasFlag(OrderFlagEnum orderFlagEnum, Long orderFlag) {return (orderFlag orderFlagEnum.getFlag()) ! 0;
}引申一下如果需要在一个字段中记录多个标记通过位运算又该怎么实现呢
比如说想要在一个字段中记录两个标记。
还是可以通过不同位置标记1还是0实现比如一个Long型标记可以在低53位记录一个标记在高10位记录另一个标记。
// 初始标记
Long flag 0L;
// 低位需要记录的标记
Long lowFlag 1L 11L;
// 高位需要记录的标记
Long highFlag 1L 3L;// 设置低位的标记
flag | lowFlag;
// 设置高位的标记
flag | (highFlag 53);// 判断是否设置低位标记
System.out.println((flag lowFlag) ! 0);// true
// 判断是否设置高位标记
System.out.println((flag 53L highFlag) ! 0); // true同理如果需要在一个字段记录多个标记只需要划分不同的标记区间就可以了。
比如Java中的读写锁ReentrantReadWriteLock就是通过在内部表示锁状态的state变量上的低16位表示写锁高16位表示读锁 这里为什么这么设计呢而不是维护一个读锁一个写锁是因为通过CAS的方式无法一次性操作两个变量