位图简介与模拟

基本概念

创建一个字节数组,将每一个字节下的8比特位存放某种状态,适用于海量数据,整数,无重复数据的场景,通常用来判断某个数据存不存在

 

实现原理

数据是否存在于给定的数据中,其答案无非与是在或者不在,刚好是两种状态,二计算机中比特位的状态正好也是两种状态----0 or 1.那么就可以正好使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,则代表存在。如果为0,则代表不存在.如图

由上图可得,有7个整形,共需要28个字节,但我们使用位图的话,只需要3个字节,且如果数组的最大值不超过23,使用位图的话也只需要三个字节,这就意味着如果要存储一个1,2,3······23的整型数组,我们只需要使用三个字节即可知道其数组里面的值是否存在的情况,而很明显地可以节省很多空间----4X24=96个字节只需要3个字节的存储,而这也就是位图的精妙之处

代码

在Java自带的util包下的BitSet类就已经实现好了位图的功能,其方法主要有这几个:

  • set(int val):将val值对应的bit位下标值设置成1
  • boolean get(int val):获取val值对应的bit位下标值
  • reSet(int vak):将val值对应的bit位下标值重新设置为0
public class bitset {
    public static void main(String[] args) {
        //Java自身带的位图类---BitSet
        BitSet bitSet = new BitSet(11);//开辟nbits/8+1个字节的数组byte[] bytes = new byte[nbits/8+1]
        int[] arr = {3,9,5,4,0,11};
        for(int i = 0; i <arr.length; i++){
            bitSet.set(arr[i]);//将整形数组中的数映射到字节数组中,存在的数将位设置为1
        }
        System.out.println(bitSet.get(11));//true
        System.out.println(bitSet.get(12));//不在数组范围内 --- false
    }
}

模拟实现

定义类

public class myBitSet {
    //模拟实现位图
    public byte[]bytes;
    public int usedSize;
    //构造方法
    public myBitSet(int n){ //传入的位数 其字节数组长度应设置为:n / 8 +1 最坏的情况也就是当n为8的整数倍时
                            //会浪费1个字节,当然这也是微乎其微的
        //初始数组
        bytes = new byte[n /8 +1];
    }

set方法  ----- 将目标位下标变成1  或上一个左移bitIndex了的1即可

//set
    public void set(int val){
        //找到数组下标
        int arrayIndex = val / 8;
        //找到一个字节对应位的下标
        int bitIndex = val % 8;
        //将其位下标值设置成1----使用|  不能使用异或^
        //如果写成:bytes[arrIndex] = (bytes[arrIndex] | (1 << bitIndex))就需要强制转换 provided:int
        bytes[arrayIndex] |= (1 << bitIndex);//使用运算符会整形提升,会被提升成int,所以这时候不需要强转
        usedSize++;
    }

  

get方法 ----- 获取val值对应bit下标的状态位

 //get
    public boolean get(int val){
        //数组下标
        int arrayIndex = val / 8;
        //位下标
        int bitIndex = val % 8;
        //&一个1
        int ret = bytes[arrayIndex] & (1 << bitIndex);
        if(ret != 0){
            return true;
        }
        return false;
    }

  

reSet方法:将val对应的位下标重新设置为0

 //将val对应的位下标重新设置成0
    public void reSet(int val){
        //数组下标
        int arrayIndex = val / 8;
        //位下标
        int bitIndex = val % 8;
        //将目标的1变成0,其他的0和1都不变 将1左移bitIndex位后取反再与操作
        bytes[arrayIndex] &= ~(1 << bitIndex);
        usedSize--;
    }

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值