之前看到关于缓存击穿相关文章时, 延伸到了布隆过滤器和bitmap算法。
验证了解之后,觉得应该写下了,不然总是遗忘。
所谓BitMap就是用一个bit位来标记元素的值。
这句话咋理解捏?我们来慢慢分析!
一:
举个栗子,来具象了解算法原理,假如有这么几个随机数,前提是不重复,int arr[]={4,7,11,2,5},如何
将这几个标记在bitmap中呢?
开始;
在java中一个最小存储单位为byte(子节),1byte=8bit,新建一个byte数组,byte[] bits=new byte[2]; 那么arr中的元素
在bits中的标记就如下图:(新建两个byte数组,每个byte的bit位都置为0,0表示未出现,1表示出现,这里默认为Little-ending)
看完这张图,大概知道bitmap的基本原理,bit位所在下标就是值的表达,是不是很神奇?
一个int类型数据占4个byte也就是32bit而用bitmap来表示只需要一个bit,理论上是缩减了32倍的空间。
二:
看到这新的问题出现,那通过怎样的计算,来实现标记呢?其实就是和8这个数字相关的运算,因为一个byte有8个bit啊!
如果我们的数字不超过7那就好办了,一个byte就搞定了,怎样确定位置呢?
position=N%8 N呢就是我们的目标数,%8找到下标位置。
但是,现实中数字可不是只有到7 ,当目标数为8的时候呢? 发现下标也为0,这是不是相当于占据了目标0的位置呢?
看看上图,其实并不是,按照bitmap的算法,8应该是占据第二个byte的0的位置。
所以我们需要第二个关键位置,就是目标数字所在的byte的[index] ,很简单index=N/8=N>>3。
当两个关键位置都有了,我们就可以个写一个简单的bitmap类,来实际感受下这个神奇算法(看完了很简单,反正我是想不到,嘎嘎)
三:
code:
public class BitMap {
/**
* 创建数组
*/
public byte[] bits;
public void consoleBytes(byte b){
byte[] array = new byte[8];
for(int i = 7; i >= 0; i--){
array[i] = (byte)(b & 1);
b = (byte)(b >> 1);
}
for (byte b1 : array) {
System.out.print(b1);
System.out.print(" ");
}
System.out.println();
}
/**
* 初始化构造执行byte数组扩容
* @param num
*/
public BitMap(int num){
bits=new byte[getIndex(num)+1];
for(int i = 0; i < num; i++){
add(i);
}
int index = 1;
for(byte bit : bits){
System.out.println("-------" + index++ + "-------");
consoleBytes(bit);
}
}
/**
* 一个byte=8个bit,所以除8,取到num在byte数组的位置
* @param num
* @return
*/
public int getIndex(int num){
return num>>3;
}
/**
* num%8得到在byte[index]的位置
* @param num
* @return
*/
public int getPosition(int num){
return num % 8;
}
/**
* bitmap中添加数据num,标记type中的bit为1,证明存在
* 将1左移指定位长,然后与当前的byte做| ,则当前位置替换为1
* @param num
*/
public void add(int num){
int idx=getIndex(num);
int po=getPosition(num);
System.out.println(bits[idx]);
bits[idx]|=1<<po;
}
/**
* 判断指定数字num是否存
* 将1左移position后,那个位置自然就是1,然后和以前的数据做&,判断是否为0即可
* @param num
* @return
*/
public boolean contains(int num){
return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;
}
/**
* 重置某一数字对应在bitmap中的值
* 对1进行左移,然后取反,最后与byte[index]作与操作。
* @param num
*/
public void clear( int num){
bits[getIndex(num)] &= ~(1 << getPosition(num));
}
public static void main(String[] args) {
BitMap bt=new BitMap(100);
System.out.println(bt.contains(101));
}
}