位移在枚举中的应用


位移在枚举中的应用

最近在公司代码中发现一个枚举类中使用了位移来表示枚举值,不是很能理解为何这样设置,遂去问了度娘和老同事。大概意思就是存在多个枚举组合使用的情况下使用位移能很方便的分辨出是哪些枚举。

public enum BusinessType {
    A("AAA", 1 << 0),
    B("BBB", 1 << 1),
    C("CCC", 1 << 2);
}

如上是一个产品线枚举,如果想判断某个产品是否同时属于产品线A和产品线B,可以这样子来判断:

    Integer type = BusinessType.A.getCode() + BusinessType.B.getCode();
    if ((obj.getBusinessType() & type) == type) {

    }

举一反三,在检验场景中的使用

接上次的检验场景,表单对象中的用户可选的标签中有几个有冲突不能同时选择,在保存表单对象必须对这些情况进行检验。

1.构建枚举类

很幸运,公司代码中已经有用户选择标签的枚举类了,但是没有可供使用的位移枚举值,因此扩展一下,如下:

public enum Label {
    A("AAA", 1 << 0),
    B("BBB", 1 << 1),
    C("CCC", 1 << 2);
    D("DDD", 1 << 3);
}

2.设计冲突规则&计算校验和

比如,A和B不能同时选择校验规则,至少选择一个标签,当然也适用比较复杂的校验规则,如必须ABCD之间自由组合,这些规则可以按如下设计:

    // AB不能同时选择
    Integer ABConflictRule = Label.A.getCode() + Label.B.getCode();

    // 至少选择一个
    Integer leastOneCheckedRule = ABConflictRule + Label.C.getCode() + Label.D.getCode();

    List<Integer> complexCheckRule = Lists.newArrayList(
                            Label.A.getCode(),
                            Label.B.getCode(),
                            Label.C.getCode(),
                            Label.D.getCode(),
                        );

冲突规则设计完毕之后,就需要计算所选择标签的校验和了,

    int checkSum = 0;
    for (Label label : query.getLabels()) {
        checkSum += Lable.descOf(label.getDesc).getCode();
    }

3.进行校验

对校验和和冲突规则使用位移运算,然后根据位移运算之后的结果判断是否冲突,如:

    if ((ABConflictRule & checkSum) == ABConflictRule) {
        System.out.println("AB冲突了");
    }

    if ((leastOneCheckedRule & checkSum) == 0) {
        System.out.println("没有选择标签");
    }

    // 也可以这样
    if (chcksum == 0) {
        System.out.println("没有选择标签");
    }

    // 至少选择一个标签 && 不能选择一个标签 = ABCD之间自由组合
    if ((leastOneCheckedRule & checkSum) == 0 && complexCheckRule.contains(checkSum)) {
        System.out.println("标签之间没有自由组合");
    }

最后一个校验稍微有点复杂,需要进行一下换算。

总结

位移运算在工作中很少使用到,以前只知道位移效率高,可以用来替代 乘法 和 除法。对位移运算的理解和应用也仅仅只限于熟悉运算规则并进行计算而已,很难想到上面这种通过位移来进行筛选。其实关于上面这些操作在离散数学中都有介绍,只能怪自己当初摸鱼了(囧)。。。

现在总结一下位移运算一些很有特点的操作:

  • 交集:A & B
  • 并集:A | B
  • 差集: A & (~B)

最后,在网上发现一些关于位移运算技巧:位运算有什么奇技淫巧?


文章作者: Ning0h2o
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ning0h2o !
评论
评论
 上一篇
Java日志体系概述 Java日志体系概述
Java日志体系概述平时自己写代码很少使用日志,对Java日志这方面的知识也有所欠缺。现在工作中要求在代码中使用合理地打上一些日志,这几天也有去了解Java日志有关的一些知识,这篇文章也是对最近几天的学习进行一些总结。 为什么要有Java日
2020-09-13
下一篇 
责任链模式在字段验证场景中的使用 责任链模式在字段验证场景中的使用
责任链模式在字段验证场景中的使用最近在搬砖过程中有一个保存大表单的需求(搬砖CRUD常态),在保存这个大表单之前有一系列的检验(字段校验使用了JSR303),表单名不能和已有的重名、表单数量、同时还有一些字段是互斥不能同时选择的等等一些情况
2020-08-24
  目录