位运算是java中比较基础的知识,位运算的计算速度很快,jdk中不少源码都是使用位运算(例如ArrayList,HashMap)
。
但是在日常开发的过程中,我们很少会使用位运算。相比较它的计算速度的优点,它可读性不高的”缺点“似乎对于普通的业务开发来说更加突出。
我们更加乐意直接使用 +,-,*,/
这些直接的运算符。
本文将给大家介绍一种位运算在业务中的应用场景,希望能给大家带来帮助,如有不对之处,欢迎指正。
本位不对位运算的基础做展开介绍,如果不熟悉位运算的基础概念的,请先自行google了解。
日常业务开发的过程中,经常会有对业务模型打标 (true/false) 的需求。
例如:
true表示男生,false表示女生
true表示参与活动优惠,false表示无法参与活动优惠
true表示超级管理员,false表示普通用户
.....
一般情况下针对这种需求,我们通常会使用一个独立的字段去表示Domain的状态。随着业务的发展,需要打标的逻辑越来越多。对应到Domain/表结构中标识的字段也会不断的上升。
- @Data
- public class User {
- private Long userId;
- private String userName;
- private boolean canLogin;
- private boolean isMale;
- private boolean isAdmin;
- ....
- }
- 复制代码
为了解决这种非A即B的字段标识的膨胀问题,我们可以使用位运算去整合这些字段。
例如上文展示的User Domain,我们整合canLogin,isMale,isAdmin为一个字段,认为是一个feature标识(设置字段为featureTag
)。
- @Data
- public class User {
- private Long userId;
- private String userName;
- private int featureTag;
- }
- 复制代码
我们可以定义一个feature的枚举定义每一位标识什么
- public enum UserFeatureEnum{
-
- CAN_LOGIN(0),
- IS_MALE(1);
- IS_ADMIN(2);
-
- private int bit;
-
- UserFeatureEnum(int bit) {
- this.bit = bit;
- }
-
- public int getValue() {
- return this.bit;
- }
-
- }
- 复制代码
然后我们可以通过一下的BitUtil来check当前用户某个特性的状态
- public class BitUtil {
- public static int setBit(int options, int bitIndex) {
- int val = 1 << bitIndex;
- return options | val;
- }
-
- public static int unsetBit(int options, int bitIndex) {
- int val = 1 << bitIndex;
- return options & (~ val);
- }
-
- public static boolean isBitSetted(int options, int bitIndex) {
- int val = 1 << bitIndex;
- return (options & val) == val;
- }
-
- public static boolean isBitUnSetted(int options, int bitIndex) {
- int val = 1 << bitIndex;
- return (options & val) == 0;
- }
- }
- 复制代码
这样我们如果去校验user是否为男性就可以这么操作
- boolean isMale = BitUtil.isBitSetted(user.getfeatureTag(),UserFeatureEnum.IS_MALE.getValue());
- 复制代码
设置当前用户为女性
- user.setfeatureTag(BitUtil.unsetBit(user.getfeatureTag(),UserFeatureEnum.IS_MALE.getValue()))
- 复制代码
设置当前用户为男性
- user.setfeatureTag(BitUtil.setBit(user.getfeatureTag(),UserFeatureEnum.IS_MALE.getValue()))
- 复制代码
这样我们将日益膨胀的标志字段给合并了,数据库也能够只用一个字段就能够标识Domain的多个feature。
后续如果需要增加一个feature时,就不需要修改表结构了,只需要增加一个枚举值及设置、判断逻辑就行。
像线上项目,改个表结构还要走一道道的DBA审批流程
作者:柏炎
原文链接:
不谈源码,聊聊位运算的实际应用 - 掘金