简版位图

场景:咱不知道其他人是什么场景用它的,咱也不知道当初为啥要用这个,但是既然这个用到这个了,那咱就说道说道吧。项目中用到的场景是客户招揽中有多个任务类型,分为首保、定保、保修、保险、召回、主题等,一共这么多种类型,然后它在查询的时候会有这样一种场景,它可能会查既是首保,又是保险的任务类型,也有可能查询既是首保、保修,同时又是主题的任务类型。也就是说他查询的任务类型不只是这一种,他可能出现同时查很多种的情况。那么这个时候怎么做呢?位图就为这个提供了一种解决问题的思路。

算法:

假如有几种类型,分别是首保、定保、保修、保险、维修、主题

定义一个常量,将上面的六种类型分别用二进制位表示出来,

如:首保 = 1<<0(00000001),定保= 1<<1(00000010),保修 = 1<<2(00000100),

       保险 = 1<<3(0001000),维修 = 1<<4(00010000),主题 = 1<<5(00010000)

假如前端插入的时候选择了 首保、定保两种类型的数组,那么存的时候不能存 首保和定保,这时候需要将它们做转化,根据上面的每种类型的二进制数字,转化成一个数字存到数据库中。

如果要查包含某种类型的数据,遵照相与原则还等于这个数来判断。

 

计算数组,将数组值转为存进数据库的值:

public static synchronized Integer orArray(List<Integer>list) {
	flag=0;

	for(int index=0; index<list.size(); index++) {
		flag = (1 << (list.get(index).intValue()-1)) | flag;
	}
	return flag;
}

上面算出的值是存到数据库的结果.

下面就是如何通过查找来查出来了,根据上面的相与原则,首先也是要将前端传来的类型进行处理,首先左移成二进制,变成我们上面的 00000001 这种形式,再转为十进制与数据库中存的数据作对比:

public static synchronized Integer getDataByCardEnum(CardTypeEnum cardTypeEnum){ 

	return 1 << (cardTypeEnum.getNum() - 1);
}

上面就将数据转换好了,最后根据相与原则与数据库中的作对比:

程序中用MP的方式, 为了方便我只展示了作比较的那一行:

wrapper.eq("last_solicit_task_code_num&"+taskTypeValue+"",taskTypeValue);

其中last_solicit_task_code_num数据库中的值就是开始插入时候存入的值,taskTypeValue就是我们查询时前端传入并经我们转换之后的值,相与后等于taskTypeValue,则数据库中的这条数据就是包含我们查询条件的数据。

 

 

PS: 写的可能不太清楚,后面是二进制转换后比较的举例, 希望可以协助大佬们理解: 

首保 = 1<<0(00000001,1),定保= 1<<1(00000010,2),保修 = 1<<2(00000100,3),保险= 1<<3(00010000,4),维修 = 1<<4(00010000,5),主题= 1<<5(00010000,6)

包含 首保、定保,存到数据库中是3,用二进制表示为:

00000011

查询包含 首保 的,首保是1,用二进制表示为:

00000001

那么根据相与原则,同位为1,异位为0可得

00000011

00000001

——————

00000001

由上最后得出的结果还是为首保,所以该数据包含首保;

假如我查询包含 保险 的,保险是4,用二进制表示为:

00010000

那么

00000011

00010000

——————

00000000

得到的值为0,说明该数据不包含保险。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值