BitMap從字面的意思,不少人認爲是位圖,其實準確的來講,翻譯成基於位的映射,怎麼理解呢?
複製代碼
舉一個例子,有一個無序有界int數組{1,2,5,7},初步估計佔用內存44=16字節,這卻是沒什麼奇怪的,可是假若有10億個這樣的數呢,10億4/(102410241024)=3.72G左右。若是這樣的一個大的數據作查找和排序,那估計內存也崩潰了,有人說,這些數據能夠不用一次性加載,那就是要存盤了,存盤必然消耗IO。咱們提倡的是高性能,這個方案直接不考慮。java
若是用BitMap思想來解決的話,就好不少,那麼BitMap是怎麼解決的啊,以下: 一個byte是佔8個bit,若是每個bit的值就是有或者沒有,也就是二進制的0或者1,若是用bit的位置表明數組值有仍是沒有,那麼0表明該數值沒有出現過,1表明該數組值出現過。不也能描述數據了嗎?以下圖: 算法
是否是很神奇,那麼如今假如10億的數據所需的空間就是3.72G/32了吧,一個佔用32bit的數據如今只佔用了1bit,節省了很多的空間,排序就更不用說了,一切顯得那麼順利。這樣的數據之間沒有關聯性,要是讀取的,你能夠用多線程的方式去讀取。時間複雜度方面也是O(Max/n),其中Max爲byte[]數組的大小,n爲線程大小。數組
若是BitMap僅僅是這個特色,我以爲還不是它的優雅的地方,接下來繼續欣賞它的魅力所在。下面的計算思想其實就是針對bit的邏輯運算獲得,相似這種邏輯運算的應用場景能夠用於權限計算之中。 再看代碼以前,咱們先搞清楚一個問題,一個數怎麼快速定位它的索引號,也就是說搞清楚byte[index]的index是多少,position是哪一位。舉個例子吧,例如add(14)。14已經超出byte[0]的映射範圍,在byte[1]範圍之類。那麼怎麼快速定位它的索引呢。若是找到它的索引號,又怎麼定位它的位置呢。Index(N)表明N的索引號,Position(N)表明N的所在的位置號。多線程
Index(N) = N/8 = N >> 3;性能
Position(N) = N%8 = N & 0x07;this
基於上面的分析,咱們寫一個簡單的BitMap的算法以下:spa
public class BitMap {
//保存數據的
private byte[] bits;
//可以存儲多少數據
private int capacity;
public BitMap(int capacity){
this.capacity = capacity;
//1bit能存儲8個數據,那麼capacity數據須要多少個bit呢,capacity/8+1,右移3位至關於除以8
bits = new byte[(capacity >>3 )+1];
}
public void add(int num){
// num/8獲得byte[]的index
int arrayIndex = num >> 3;
// num%8獲得在byte[index]的位置
int position = num & 0x07;
//將1左移position後,那個位置天然就是1,而後和之前的數據作|,這樣,那個位置就替換成1了。
bits[arrayIndex] |= 1 << position;
}
public boolean contain(int num){
// num/8獲得byte[]的index
int arrayIndex = num >> 3;
// num%8獲得在byte[index]的位置
int position = num & 0x07;
//將1左移position後,那個位置天然就是1,而後和之前的數據作&,判斷是否爲0便可
return (bits[arrayIndex] & (1 << position)) !=0;
}
public void clear(int num){
// num/8獲得byte[]的index
int arrayIndex = num >> 3;
// num%8獲得在byte[index]的位置
int position = num & 0x07;
//將1左移position後,那個位置天然就是1,而後對取反,再與當前值作&,便可清除當前的位置了.
bits[arrayIndex] &= ~(1 << position);
}
public static void main(String[] args) {
BitMap bitmap = new BitMap(100);
bitmap.add(7);
System.out.println("插入7成功");
boolean isexsit = bitmap.contain(7);
System.out.println("7是否存在:"+isexsit);
bitmap.clear(7);
isexsit = bitmap.contain(7);
System.out.println("7是否存在:"+isexsit);
}
}
複製代碼