美文网首页
位枚举应用-学会Java位枚举

位枚举应用-学会Java位枚举

作者: Running的程序员 | 来源:发表于2022-10-16 02:18 被阅读0次

作为开发者,掌握位枚举的开发技能可以帮助我们加快业务需求开发,提高系统性能

什么是位枚举?其实理解和掌握位枚举并不复杂。下面我们以传统的枚举来进行对比说明,助你加深对位枚举的理解和应用。

假如我们系统中有一个表示兴趣爱好的枚举类EnumHobbyType。那么我们会有如下两种实现方式

1.传统枚举实现方式

传统形式的枚举类信息如下:

public enum EnumHobbyType {

    DEFAULT(0, "无爱好"),
    SING(1, "唱歌"),
    DANCE(2, "跳舞"),
    SWIMMING(3, "游泳"),
    GAME(4, "打游戏"),
    COOKING(5, "烹饪"),
    ;


    EnumHobbyType(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

    private Integer code;
    private String name;

    public Integer getCode() {
        return code;
    }

    public String getName() {
        return name;
    }
}

很显然,当我们以传统形式的枚举去表示爱好时,那么对应的我们的数据库表中对应的字段存储的值形式会是下图这样的格式(在代码层面,保存前我们会以指定符号拼接hobby字段)

枚举项拼接保存.png

与保存时对应,当页面查询时,我们的系统去查询库表,在代码层面我们一般会进行如下处理,把hobby字段进行切割:

String[] hobbies= StringUtils.split(hobby, ",");

以上处理过程,保存前拼接为字符串,查询时再切割字符串为数组,实际上性能会存在损耗,后期扩展也有些麻烦。所以就该我们的主角:位枚举现身了。

2.位枚举实现方式

位枚举是指利用位运算实现的枚举类,枚举的code以2的幂数依次递增。这样的话我们就可以利用按位或运算、按位与运算去快速的处理和枚举相关的业务。说到位运算大家第一反应应该就是速度快了。具体怎么玩呢?如下:
位枚举的实现的hobby枚举类

/**
 * 枚举项请以2的幂数递增,如: 1,2,4,8,16,32,64,128...
 */
public enum EnumHobbyType {

    DEFAULT(0L, "无爱好"),
    SING(1L, "唱歌"),
    DANCE(2L, "跳舞"),
    SWIMMING(4L, "游泳"),
    GAME(8L, "打游戏"),
    COOKING(16L, "烹饪"),
    ;


    EnumHobbyType(Long code, String name) {
        this.code = code;
        this.name = name;
    }

    private Long code;
    private String name;

    public Long getCode() {
        return code;
    }

    public String getName() {
        return name;
    }


    public static boolean isHasFlag(final Integer flag, final EnumHobbyType hobbyType) {
        if (Objects.isNull(flag) || Objects.isNull(hobbyType)) {
            return false;
        }

        if (DEFAULT.getCode().equals(flag)) {
            return false;
        }

        Long code = hobbyType.getCode();
        //一个整数 按位与自身 = 自身值
        return (code & flag) == code;
    }

    /**
     * 传入爱好枚举的整数结果,和每一项枚举项code进行按位与运算  可判定爱好中是否有此爱好项
     * @param flag
     * @return
     */
    public static List<EnumHobbyType> getHitFlags(final Integer flag) {
        if (Objects.isNull(flag)) {
            return Collections.emptyList();
        }

        if (DEFAULT.getCode().equals(flag)) {
            return Collections.emptyList();
        }

        List<EnumHobbyType> hitFlags = new ArrayList<>();
        for (EnumHobbyType value : values()) {
            if (value.getCode().equals(DEFAULT.getCode())) {
                continue;
            }
            Long code = value.getCode();
            //传入给定整数和任意一个枚举项进行按位与运算
            if ((code & flag) == code) {
                //结果等于枚举项本身,说明flag中有此枚举项
                hitFlags.add(value);
            }
        }
        return hitFlags;
    }

    /**
     * 把枚举项进行按位或运算 得到所有爱好的整数结果
     * @param hobbyTypes
     * @return
     */
    public static Long calculateFlag(List<EnumHobbyType> hobbyTypes) {
        if (CollectionUtils.isEmpty(hobbyTypes)) {
            return DEFAULT.getCode();
        }

        Long value = 0L;
        for (EnumHobbyType propertyFlag : hobbyTypes) {
            //将爱好list值进行按位或运算
            value |= propertyFlag.getCode();
        }

        return value;
    }

}

位枚举的核心要点如下

  1. 枚举项请以2的幂数递增,如: 1,2,4,8,16,32,64,128...
  2. 任意两数m和n,如果m和n都是2的幂数,那么m和n进行按位或运算的结果就等于m和n的字面值相加,什么意思呢?即m|n = m+n,如m=2,n=4,那么m|n = 6。此处等价于加法运算
  3. 任意两数m和n,如果m和n都是2的幂数,p是m和n按位或的结果,那么就有p&n=n,p&m=m,类似于减法运算

这时候我们系统怎么保存和查询hobby呢?用位枚举的方式就变得很简单方便了,比如张三的爱好有唱歌、打游戏、烹饪,那么保存时我们直接调用封装的方法calculateFlag得到张三最终的爱好结果即可,唱歌|打游戏|烹饪=25(1|8|16=25,位运算速度极快),按位或运算结果图如下:

枚举项进行按位或运算.png 数据库表的保存结果为: 保存或运算结果.png

查询时怎么处理呢?很简单,从表中查询到hobby,比如此处hobby值为25,怎么知道25有哪些爱好组成呢?直接调用位枚举类中封装的方法getHitFlags,可快算获取到hobby(25)对应的枚举项有:唱歌、打游戏、烹饪(25&唱歌=唱歌,25&打游戏=打游戏,25&烹饪=烹饪)。运算结果截图如下:

字段值和枚举项进行按位与运算.png

合理利用位运算可以提升我们代码处理速度,位运算的应用很多,位枚举作为一种应用场景,对我们开发有很好的帮助。可以多多动手实践下,好好理解,为你自己所用。

OK,咱们后面回聊儿~

相关文章

  • OC中按位枚举的说明以及用法

    OC中枚举类型有两种, 普通枚举和按位枚举 1 普通枚举 };2 按位枚举 };3 这个例子可以看出,两种枚举在声...

  • 位运算与位枚举

    位运算与位枚举

  • iOS 位枚举

    在 iOS 开发中,我们使用系统的枚举定义的时候,经常可以看到位枚举: 需要掌握位枚举,我们需要先了解位运算 和 ...

  • Java初级笔记No.4(更新中)

    2018.7.27 1、Java的主要内置数据结构包括:枚举(Enumeration),位集合(BitSet),向...

  • c枚举,位运算

  • 位运算和枚举

    我看iOS本身定义的枚举里面经常会使用左移(<<)来定义枚举的值,一开始我还不懂为啥要这么定义。这么处理的逻辑跟i...

  • 枚举

    枚举 wiki Java的枚举类型用法介绍 深入理解Java枚举类型(enum) 为什么要用enum? 学习计划 ...

  • Java枚举

    Java中的每个枚举都是java.lang.Enum的final子类,枚举类中的每个枚举常量都是该枚举类的一个实例...

  • 第四讲 枚举法一

    第四讲 枚举法一 内容概述 掌握枚举的一般方法。学会按照一定顺序,有规律地进行枚举,做到“不重不漏”;应用字典排列...

  • Java数据结构

    Java工具包中包含许多强大的数据结构,主要包括 枚举(Enumeration); 位集合(BitSet); 向量...

网友评论

      本文标题:位枚举应用-学会Java位枚举

      本文链接:https://www.haomeiwen.com/subject/duurzrtx.html