import org.apache.commons.lang3.StringUtils;
/**
* @author : zanglikun
* @date : 2025/11/3 10:21
* @desc : 分省其他信息枚举
* 下文信息已脱敏
*/
public enum ProvinceMisc {
// 掩码值、 描述、 数值、 分省ID
// 掩码值 格式是:1 << X 其中X从0递增,按照业务叠加即可。
WGS(1 << 0, "W公司", 111),
CHAO_GAO_YA(1 << 1, "超高压", 222),
GUANG_DONG(1 << 2, "广东", 333),
GUANG_XI(1 << 3, "广西", 444),
YUN_NAN(1 << 4, "云南", 555),
GUI_ZHOU(1 << 5, "贵州", 666),
HAI_NAN(1 << 6, "海南", 777),
SHEN_ZHEN(1 << 7, "深圳", 888);
// 基础信息
private final int mask;
private final String desc;
private final int value;
ProvinceMisc(int mask, String desc, int value) {
this.mask = mask;
this.desc = desc;
this.value = value;
}
public int getMask() {
return mask;
}
public String getDesc() {
return desc;
}
public int getValue() {
return value;
}
public static ProvinceMisc fromValue(int value) {
for (ProvinceMisc misc : ProvinceMisc.values()) {
if (misc.value == value) {
return misc;
}
}
return null;
}
public static ProvinceMisc fromProvinceName(String desc) {
for (ProvinceMisc misc : ProvinceMisc.values()) {
if (StringUtils.equals(misc.desc, desc)) {
return misc;
}
}
return null;
}
}
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author : zanglikun
* @date : 2025/11/3 10:12
* @desc : 位运算工具类。采用位运算实现对多个指标的组合查询和管理。
* <a href="https://www.zanglikun.com/12441.html#%e5%88%a9%e7%94%a8%e4%bd%8d%e8%bf%90%e7%ae%97%e8%a1%a8%e7%a4%ba%e7%8a%b6%e6%80%81">查看类似说明</a>
*/
@Slf4j
public class ProvinceMiscUtils {
/**
* 判断是否包含某个指标
*
* @param provinceMisc 指标组合值(掩码值)- 由多个指标的掩码按位或组合而成
* 示例:0x1F (31) 表示包含多个指标
* @param province 要检查的指标对象 - ProvinceMisc 枚举值
* 示例:ProvinceMisc.ADD_COUNT
* @return true 表示该指标已包含;false 表示未包含
* 原理:通过按位与操作判断是否存在
*/
public static boolean hasProvince(int provinceMisc, ProvinceMisc province) {
return (provinceMisc & province.getMask()) != 0;
}
/**
* 添加一个指标
*
* @param provinceMisc 当前指标组合值(掩码值)
* @param province 要添加的指标 - ProvinceMisc 枚举值
* @return 新的指标组合值(掩码值)
* 原理:通过按位或操作合并掩码
*/
public static int addProvince(int provinceMisc, ProvinceMisc province) {
return provinceMisc | province.getMask();
}
/**
* 移除一个指标
*
* @param provinceMisc 当前指标组合值(掩码值)
* @param province 要移除的指标 - ProvinceMisc 枚举值
* @return 新的指标组合值(掩码值),该指标已被移除
* 原理:通过按位与非操作清除特定掩码位
*/
public static int removeProvince(int provinceMisc, ProvinceMisc province) {
return provinceMisc & ~province.getMask();
}
/**
* 批量添加指标,得到结果是新的值
*
* @param provinceMisc 初始指标组合值(掩码值)默认是0
* @param provinces 可变长参数 - 多个要添加的指标
* 示例:addProvinces(0, ADD_COUNT, UPDATE_COUNT, DELETE_COUNT)
* @return 最终的指标组合值(掩码值)
*/
public static int addProvinces(int provinceMisc, ProvinceMisc... provinces) {
for (ProvinceMisc province : provinces) {
provinceMisc = addProvince(provinceMisc, province);
}
return provinceMisc;
}
/**
* 批量添加指标,得到结果是新的值
*
* @param provinceMisc 初始指标组合值(掩码值)默认是0
* @param provinceList 多个要添加的指标列表
* 示例:addProvinces(0, Lists.newArrayList("1","2"))
* @return 最终的指标组合值(掩码值)
*/
public static int addProvinces(int provinceMisc, List<ProvinceMisc> provinceList) {
for (ProvinceMisc province : provinceList) {
provinceMisc = addProvince(provinceMisc, province);
}
return provinceMisc;
}
/**
* 批量移除指标
*
* @param provinceMisc 初始指标组合值(掩码值)
* @param provinces 可变长参数 - 多个要移除的指标
* @return 最终的指标组合值(掩码值)
*/
public static int removeProvinces(int provinceMisc, ProvinceMisc... provinces) {
for (ProvinceMisc province : provinces) {
provinceMisc = removeProvince(provinceMisc, province);
}
return provinceMisc;
}
/**
* 批量移除指标,得到结果是新的值
*
* @param provinceMisc 初始指标组合值(掩码值)
* @param provinceList 多个要添加的指标列表
* 示例:addProvinces(0, Lists.newArrayList("1","2"))
* @return 最终的指标组合值(掩码值)
*/
public static int removeProvinces(int provinceMisc, List<ProvinceMisc> provinceList) {
for (ProvinceMisc province : provinceList) {
provinceMisc = removeProvince(provinceMisc, province);
}
return provinceMisc;
}
/**
* 获取所有包含的指标列表
*
* @param provinceMisc 指标组合值(掩码值)- 由多个指标按位或组成
* 示例:31 (0x1F) 可能包含 ADD_COUNT、UPDATE_COUNT 等
* @return 该掩码值包含的所有指标枚举对象列表
* 示例返回:[ADD_COUNT, UPDATE_COUNT, DELETE_COUNT]
*/
public static List<ProvinceMisc> getIncludedProvinces(int provinceMisc) {
List<ProvinceMisc> list = new ArrayList<>();
for (ProvinceMisc province : ProvinceMisc.values()) {
if (hasProvince(provinceMisc, province)) {
list.add(province);
}
}
return list;
}
/**
* 获取所有包含的指标描述
*
* @param provinceMisc 指标组合值(掩码值)
* 示例:0x1F (31)
* @return 包含的所有指标的描述文本列表
* 示例返回:["新增数量", "更新数量", "删除数量"]
*/
public static List<String> getProvinceDescs(int provinceMisc) {
return getIncludedProvinces(provinceMisc)
.stream()
.map(ProvinceMisc::getDesc)
.collect(Collectors.toList());
}
/**
* 获取所有包含的指标值(原始值 0-4)
*
* @param provinceMisc 指标组合值(掩码值)
* 掩码值与指标值的映射关系:
* - 指标值(0-4):ProvinceMisc 枚举中的原始编号
* - 掩码值:2^指标值,用于位运算
* 示例:指标值为 0 时,掩码值为 2^0=1
* @return 该掩码值包含的所有指标的原始值列表
* 示例返回:[0, 1, 2, 3, 4]
*/
public static List<Integer> getProvinceValues(int provinceMisc) {
return getIncludedProvinces(provinceMisc)
.stream()
.map(ProvinceMisc::getValue)
.collect(Collectors.toList());
}
/**
* 清空所有指标
*
* @param provinceMisc 当前指标组合值(掩码值)- 不使用此参数
* @return 0 表示无指标
*/
public static int clearAllProvinces(int provinceMisc) {
return 0;
}
/**
* 检查是否为空(没有任何指标)
*
* @param provinceMisc 指标组合值(掩码值)
* @return true 表示为空(值为0);false 表示存在指标
*/
public static boolean isEmpty(int provinceMisc) {
return provinceMisc == 0;
}
/**
* 获取所有可能的指标组合(包含空集)
*
* @return 所有有效的掩码值组合列表
* 示例:如果有 3 个指标,返回 8 种组合
* [0, 1, 2, 3, 4, 5, 6, 7] 对应所有的组合方式
* 原理:2^n 种组合,其中 n 为指标总数
*/
public static List<Integer> getAllCombinations() {
int maxMask = 0;
for (ProvinceMisc province : ProvinceMisc.values()) {
maxMask |= province.getMask();
}
List<Integer> combinations = new ArrayList<>();
// 从 0 到 maxMask,所有可能的组合都会出现
for (int i = 0; i <= maxMask; i++) {
// 验证该组合是否有效(只包含已定义的指标)
if ((i & maxMask) == i) {
combinations.add(i);
}
}
return combinations;
}
/**
* 解析指标,得到执行哪些方法!
*
* @param dbConfigProvinceMisc 传入的指标组合值(掩码值)- 从数据库查询出来
* 示例:31 (0x1F) 表示需要执行多个指标对应的方法
* 掩码值说明:
* @throws IllegalArgumentException 当指标为空时抛出异常
*/
private static void parseForPrintInfo(int dbConfigProvinceMisc) {
// 验证和解析指标
List<ProvinceMisc> provinces =
ProvinceMiscUtils.getIncludedProvinces(dbConfigProvinceMisc);
if (provinces.isEmpty()) {
throw new IllegalArgumentException("请至少选择一个指标");
}
// 获取指标描述用于日志
List<String> descs = ProvinceMiscUtils.getProvinceDescs(dbConfigProvinceMisc);
log.info("查询条件, 指标: {}", descs);
}
/**
* 根据 指定匹配的字段 字段转换为 枚举对象列表
*
* @param someValue 一些值的列表
* @param objectExtractor 目标对象的提取函数 比如:ProvinceMisc::getName
* @return 分省列表
*/
public static List<ProvinceMisc> convertToProvinceList(List<String> someValue, Function<ProvinceMisc, String> objectExtractor) {
if (CollectionUtils.isEmpty(someValue)) {
return new ArrayList<>();
}
List<ProvinceMisc> result = new ArrayList<>();
for (String value : someValue) {
for (ProvinceMisc province : ProvinceMisc.values()) {
String objValue = objectExtractor.apply(province);
if (objValue.equals(value)) {
result.add(province);
break;
}
}
}
return result;
}
/**
* 根据 前端传递的值 + 以及值对应的字段 转换为掩码值。主要是用于SQL的多条件查询使用
*
* @param someValue 一些值的列表
* @param objectExtractor 目标对象的提取函数 比如:ProvinceMisc::getName
* <p>
* 场景1 查询包含所有选中条件的记录
* SELECT * FROM your_table
* WHERE (province_misc & :mask) = :mask
* <p>
* 场景2 查询包含任意一个选中条件的记录
* SELECT * FROM your_table
* WHERE (province_misc & :mask) != 0
* @return SQL条件的值
*/
public static Integer convertMultiConditionQuerySqlValue(List<Integer> someValue, Function<ProvinceMisc, Integer> objectExtractor) {
int mask = 0;
for (Integer value : someValue) {
for (ProvinceMisc province : ProvinceMisc.values()) {
Integer objValue = objectExtractor.apply(province);
if (objValue.equals(value)) {
mask = addProvince(mask, province);
break;
}
}
}
return mask;
}
/**
* 反向解析,将掩码值(数据库存储),解析为明文内容
*
* @param mask 一些值的列表
* @param objectExtractor 目标对象的提取函数 比如:ProvinceMisc::getName
* @return 明文内容列表
*/
public static List<String> convertMaskToReadableStr(Integer mask, Function<ProvinceMisc, String> objectExtractor) {
if (Objects.isNull(mask)) {
return new ArrayList<>();
}
List<ProvinceMisc> includedProvinces = getIncludedProvinces(mask);
return includedProvinces.stream().map(objectExtractor::apply).collect(Collectors.toList());
}
/**
* main 方法 - 演示和测试 ProvinceMiscUtils 的各项功能
*/
public static void main(String[] args) {
// 示例:添加和检查指标
List<Integer> provinceIds = Arrays.asList(111, 222);
Integer mask = convertMultiConditionQuerySqlValue(provinceIds, ProvinceMisc::getValue);
System.out.println("通过组织Id,得到掩码值: " + mask);
System.out.println("通过掩码值,解析得到其代表的组织: " + convertMaskToReadableStr(mask, ProvinceMisc::getDesc));
System.out.println("如果你是查询都包含这些组织的记录,可以使用SQL条件: WHERE 1 = 1 AND (province_misc & " + mask + ") = " + mask);
System.out.println("如果你是查询包含任意一个组织的记录,可以使用SQL条件: WHERE 1 = 1 AND (province_misc & " + mask + ") != 0");
}
}
特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤
免责声明: 本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤
免责声明: 本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。
