位运算-高效解决复选问题

在 Java 中,可以使用位运算来高效地存储多个布尔值(例如复选框的选中状态)。每个布尔值可以用一个二进制位来表示,这样就可以使用一个整数(int)来存储多个选项的状态。

基本思路

假设我们有几个标签或者选项,每个选项对应一个二进制位。例如,假设有 5 个选项:

  • 选项 1
  • 选项 2
  • 选项 3
  • 选项 4
  • 选项 5

我们可以用一个 int 类型的数字来表示这 5 个选项的状态,具体映射如下:

选项 1: 1 << 0  (二进制 00001)
选项 2: 1 << 1  (二进制 00010)
选项 3: 1 << 2  (二进制 00100)
选项 4: 1 << 3  (二进制 01000)
选项 5: 1 << 4  (二进制 10000)

实现示例

以下是一个简单的示例代码,展示如何使用位运算来存储和操作这些选项。

public class BitwiseExample {
    // 定义每个选项的常量
    public static final int OPTION_1 = 1 << 0; // 1
    public static final int OPTION_2 = 1 << 1; // 2
    public static final int OPTION_3 = 1 << 2; // 4
    public static final int OPTION_4 = 1 << 3; // 8
    public static final int OPTION_5 = 1 << 4; // 16

    // 添加选项
    public static int addOption(int current, int option) {
        return current | option; // 使用 OR 操作
    }

    // 移除选项
    public static int removeOption(int current, int option) {
        return current & ~option; // 使用 AND 操作
    }

    // 检查选项是否被选中
    public static boolean isOptionSelected(int current, int option) {
        return (current & option) != 0; // 使用 AND 操作
    }

    public static void main(String[] args) {
        int selectedOptions = 0; // 初始状态

        // 选中选项1和选项3
        selectedOptions = addOption(selectedOptions, OPTION_1);
        selectedOptions = addOption(selectedOptions, OPTION_3);

        // 检查选项状态
        System.out.println("Option 1 selected: " + isOptionSelected(selectedOptions, OPTION_1)); // true
        System.out.println("Option 2 selected: " + isOptionSelected(selectedOptions, OPTION_2)); // false
        System.out.println("Option 3 selected: " + isOptionSelected(selectedOptions, OPTION_3)); // true

        // 移除选项1
        selectedOptions = removeOption(selectedOptions, OPTION_1);
        System.out.println("Option 1 selected: " + isOptionSelected(selectedOptions, OPTION_1)); // false
    }
}

import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

/**
 * 商品标签
 *
 */
@Getter
public enum GoodTagEnum {

    IMPORTANT("重点商品", 1, true),
    REPURCHASE("复购商品池", 2, true),
    DRUGSERVICE("药学服务", 4, false),
    ASSOCIATION("关联推荐", 8, false),
    EXAMINE("考核商品", 16, true),
    SP_DEVICE("特殊装置商品", 32, true),
    MEDICATION_GUIDANCE("用药指导商品", 64, true),

    ;

    /**
     * 显示文字
     */
    private String text;
    /**
     * 编码数值
     */
    private Integer code;
    /**
     * 开放维护
     */
    private boolean open;

    GoodTagEnum(String text, Integer code, boolean open) {
        this.text = text;
        this.code = code;
        this.open = open;
    }

    /**
     * 通过位或运算把多个标签组合(将多个字段复选组合成一个值插入库)
     * @param tags
     * @return
     */
    public static Integer join(List<Integer> tags) {
        Integer val = 0;
        if (tags != null) {
            for (Integer tag : tags) {
                val |= tag;
            }
        }
        return val;
    }

    /**
     * 通过位与运算分离出包含的标签(将数据库中字段拆成多个字段)
     * @param val
     * @return
     */
    public static List<Integer> split(Integer val) {
        List<Integer> tags = new ArrayList<>();
        for (GoodTagEnum tag : values()) {
            if ((val & tag.code) > 0) {
                tags.add(tag.code);
            }
        }
        return tags;
    }
}

//入库
 entity.setTags(GoodTagEnum.join(param.getTags()));
//条件筛选
 List<MtmGoodInfoEntity> list = this.lambdaQuery()
                .in(MtmGoodInfoEntity::getGoodCode,codes)
                .apply(ObjectUtil.isNotEmpty(tags), "tags & {0}", GoodTagEnum.join(tags))
                .list();
//实体类查询出赋值
  /**
     * 商品标签
     */
    private List<Integer> tagList;
  /**
     * 商品标签(二进制标志位)
     */
    private Integer tags;

    public void setTags(Integer tags) {
        this.tagList = GoodTagEnum.split(tags);
    }

代码解释

  1. 选项常量定义:每个选项使用 1 << n 表示,其中 n 是选项的索引。
  2. 添加选项:使用位或操作(|)将选项添加到当前状态中。
  3. 移除选项:使用位与操作(&)和取反操作(~)来移除选项。
  4. 检查选项状态:使用位与操作(&)来检查某个选项是否被选中。

总结

使用位运算可以非常高效地存储和管理多个布尔选项,特别是在需要处理大量选项时。希望这个示例能够帮助你理解如何在 Java 中实现这个功能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值