美文网首页
java使用二进制解决一个字段代表多个状态的问题

java使用二进制解决一个字段代表多个状态的问题

作者: jiezzy | 来源:发表于2020-03-31 17:22 被阅读0次

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

相关文章

网友评论

      本文标题:java使用二进制解决一个字段代表多个状态的问题

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