https://www.jianshu.com/p/61bf95cfc9a7
package com.king.common.utils.binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 使用二进制解决一个字段代表多个状态的问题
*
* 有没有更好的方法,处理一条记录多个状态的问题呢?
* 使用二进制位,每个位置,代表一个状态,多个位置代表多个状态,存储的时候转换为int类型存储。
*
* 以产品属性存储为例。
* 热门:0000 0001
* 新品:0000 0010
* 特卖:0000 0100
*
* 多个状态的组合
* 热门+新品:0000 0011
* 热门+特卖:0000 0101
* 热门+新品+特卖:0000 0111
*
* 存储时将二进制转换为int数值。
*
* 二进制位的查询
* 以Oracle为例,使用bitadd函数,如:
* SELECT * FROM T_PRODUCT WHERE bitand(property,1)=1
* 以Mysql为例,使用&运算符,如:
* SELECT data_code,data_value FROM `tb_ceshi_data` where ceshi_code='xxx' and data_value & 8
* java中对二进制位的处理
* 1)是否包含:&与运算符,比如:(1&3)==1
* 2)组装:|或运算符,比如 1|2=3
*
* 如果再扩展,清仓状态,可以使用 0000 1000
*
* 二进制实现的好处
* 以上内容讲解了使用二进制位来表示状态的方式,实现数据库设计和程序调用。有以下好处
* 1)存储精简
* 2)扩展性强
*
* 缺点:
* 1)增加了理解复杂度;
*
* 以下是六个状态情况的二进制与十进制存储对照表:
* 00000001 1 参数1
* 00000010 2 参数2
* 00000100 4 参数3
* 00001000 8 参数4
* 00010000 16 参数5
* 00100000 32 参数6
*
* 00000011 3 参数1+参数2
* 00000101 5 参数1+参数3
* 00000110 6 参数2+参数3
* 00000111 7 参数1+参数2+参数3
* 00001001 9 参数1+参数4
* 00001011 11 参数1+参数2+参数4
* 00001101 13 参数1+参数3+参数4
* 00001111 15 参数1+参数2+参数3+参数4
* 00010110 22 参数2+参数3+参数5
* 00111111 63 参数1+参数2+参数3+参数4+参数5+参数6
*
*---------------------------------------java中操作二进制的运算符总结(&,| , ^, ~, , >>> )-----------------------------------------
* &运算符总结
* 1.特点:二元操作符,操作两个二进制数据;两个二进制数最低位对齐,只有当两个对位数都是1时才为1,否则为0
* 2.案例:
* int a = 3 & 2 ;
* System.out.println(a); //结果为 2
* 3.分析:
* 3的二进制补码表示为:
* 00000000 00000000 00000000 00000011
* 2的二进制补码表示为:
* 00000000 00000000 00000000 00000010
* 运算:3 & 2
* 00000000 00000000 00000000 00000011
* & 00000000 00000000 00000000 00000010
* -------------------------------------------
* 00000000 00000000 00000000 00000010 二进制是2
*
* @Description
* @Author HHJ
* @Date 2019-05-20 16:14
*/
public class BinaryUtil {
private static final Logger log = LoggerFactory.getLogger(BinaryUtil.class);
/**
* 求list数值之和(list="1,2,4,8,16,32....")
* (使用场景是前端将list传入进来.后端计算list之和,然后将结果直接入库)
*
* @param list
* @return
*/
public static Integer sum(List<Integer> list) {
if (CollectionUtils.isEmpty(list)) {
return 0;
}
return list.stream().reduce(Integer::sum).orElse(0);
}
/**
* 二进制转换为十进制
*(在这种方式下,该方法无用)
*
* @param binaryString
* @return
*/
public static Integer binaryToInteger(String binaryString) {
Integer i = Integer.parseInt(binaryString, 2);
return i;
}
/**
* 以base为底数.value为值,算对数.例如
* 计算64以4为底的对数:
* double res = log(64, 4);//4*4*4=64
* Assert.isTrue(res==3)
*
* @param value
* @param base
* @return
*/
public static double log(double value, double base) {
return Math.log(value) / Math.log(base);
}
/**
* 十进制数值 转对应的list
* (使用场景是将DB中对应的int转对应的list,然后将结果返回给前端)
*
* @param data
* @return
*/
public static List<Integer> toList(Integer data) {
List<Integer> list = new ArrayList<>();
if (data <= 0) {
return list;
}
double count = log((double) data, 2d);
for (int i = 0; i < count + 1; i++) {
int n = 1 << i;
if ((data & n) == n) {
list.add(n);
}
}
return list;
}
public static void main(String[] args) {
List<Integer> realList = toList(22);
System.out.println(realList.toString());
int integer = binaryToInteger("00001011");
Assert.isTrue(11 == integer, "this expression must be true");
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(4);
list.add(8);
Integer sum = sum(list);
System.out.println("sum=" + sum);
List<Integer> realList1 = toList(sum );
System.out.println(realList1.toString());
int data = 34;
List<Integer> result = toList(data);
System.out.println("result.size:" + result.size() + "...结果:" + result.toString());
}
}
————————————————
版权声明:本文为CSDN博主「九龙冰室083」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hhj13978064496/java/article/details/90379886
网友评论