BitMap原理分析

一扔嵌、問(wèn)題引入
bitMap是位圖囤萤,其實(shí)準(zhǔn)確的來(lái)說(shuō),翻譯成基于位的映射蚯妇,舉一個(gè)例子,有一個(gè)無(wú)序有界int數(shù)組{1,2,5,7},初步估計(jì)占用內(nèi)存44=16字節(jié)暂筝,這倒是沒(méi)什么奇怪的箩言,但是假如有10億個(gè)這樣的數(shù)呢,10億4/(102410241024)=3.72G左右焕襟。如果這樣的一個(gè)大的數(shù)據(jù)做查找和排序陨收,那估計(jì)內(nèi)存也崩潰了,有人說(shuō),這些數(shù)據(jù)可以不用一次性加載务漩,那就是要存盤(pán)了拄衰,存盤(pán)必然消耗IO。我們提倡的是高性能饵骨,這個(gè)方案直接不考慮翘悉。

二、問(wèn)題分析
如果用BitMap思想來(lái)解決的話居触,就好很多妖混,解決方案如下:
一個(gè)byte是占8個(gè)bit,如果每一個(gè)bit的值就是有或者沒(méi)有轮洋,也就是二進(jìn)制的0或者1制市,如果用bit的位置代表數(shù)組值有還是沒(méi)有, 那么0代表該數(shù)值沒(méi)有出現(xiàn)過(guò)弊予,1代表該數(shù)組值出現(xiàn)過(guò)祥楣。不也能描述數(shù)據(jù)了嗎?具體如下圖:

bitMap結(jié)構(gòu).png

是不是很神奇汉柒,那么現(xiàn)在假如10億的數(shù)據(jù)所需的空間就是3.72G/32了吧误褪,一個(gè)占用32bit的數(shù)據(jù)現(xiàn)在只占用了1bit,節(jié)省了不少的空間竭翠,排序就更不用說(shuō)了振坚,一切顯得那么順利。這樣的數(shù)據(jù)之間沒(méi)有關(guān)聯(lián)性斋扰,要是讀取的渡八,你可以用多線程的方式去讀取。時(shí)間復(fù)雜度方面也是O(Max/n)传货,其中Max為byte[]數(shù)組的大小屎鳍,n為線程大小。

三问裕、應(yīng)用與代碼
如果BitMap僅僅是這個(gè)特點(diǎn)逮壁,我覺(jué)得還不是它的優(yōu)雅的地方,接下來(lái)繼續(xù)欣賞它的魅力所在粮宛。下面的計(jì)算思想其實(shí)就是針對(duì)bit的邏輯運(yùn)算得到窥淆,類(lèi)似這種邏輯運(yùn)算的應(yīng)用場(chǎng)景可以用于權(quán)限計(jì)算之中。

再看代碼之前巍杈,我們先搞清楚一個(gè)問(wèn)題忧饭,一個(gè)數(shù)怎么快速定位它的索引號(hào),也就是說(shuō)搞清楚byte[index]的index是多少筷畦,position是哪一位词裤。舉個(gè)例子吧刺洒,例如add(14)。14已經(jīng)超出byte[0]的映射范圍吼砂,在byte[1]范圍之類(lèi)逆航。那么怎么快速定位它的索引呢。如果找到它的索引號(hào)渔肩,又怎么定位它的位置呢因俐。Index(N)代表N的索引號(hào),Position(N)代表N的所在的位置號(hào)赖瞒。
Index(N) = N/8 = N >> 3;
Position(N) = N%8 = N & 0x07;

(1) add(int num)
你要向bitmap里add數(shù)據(jù)該怎么辦呢女揭,不用擔(dān)心,很簡(jiǎn)單栏饮,也很神奇吧兔。
上面已經(jīng)分析了,add的目的是為了將所在的位置從0變成1.其他位置不變.


add.png

代碼:

public void add(int num){
        // num/8得到byte[]的index
        int arrayIndex = num >> 3; 
        
        // num%8得到在byte[index]的位置
        int position = num & 0x07; 
        
        //將1左移position后袍嬉,那個(gè)位置自然就是1境蔼,然后和以前的數(shù)據(jù)做|,這樣伺通,那個(gè)位置就替換成1了箍土。
        bits[arrayIndex] |= 1 << position; 
    }

(2) clear(int num)

對(duì)1進(jìn)行左移,然后取反罐监,最后與byte[index]作與操作吴藻。

clear.png

實(shí)例代碼:

public void clear(int num){
        // num/8得到byte[]的index
        int arrayIndex = num >> 3; 
        
        // num%8得到在byte[index]的位置
        int position = num & 0x07; 
        
        //將1左移position后,那個(gè)位置自然就是1弓柱,然后對(duì)取反沟堡,再與當(dāng)前值做&,即可清除當(dāng)前的位置了.
        bits[arrayIndex] &= ~(1 << position); 

    }

(4) contain(int num)

contain.png

實(shí)例代碼:

   public boolean contain(int num){ // num/8得到byte[]的index
        int arrayIndex = num >> 3; // num%8得到在byte[index]的位置
        int position = num & 0x07; //將1左移position后矢空,那個(gè)位置自然就是1航罗,然后和以前的數(shù)據(jù)做&,判斷是否為0即可
        return (bits[arrayIndex] & (1 << position)) !=0; 
    }

全部代碼:

package com.chs.alg.bitmap;

public class BitMap {
    //保存數(shù)據(jù)的
    private byte[] bits;
    
    //能夠存儲(chǔ)多少數(shù)據(jù)
    private int capacity;
    
    
    public BitMap(int capacity){
        this.capacity = capacity;
        
        //1bit能存儲(chǔ)8個(gè)數(shù)據(jù)屁药,那么capacity數(shù)據(jù)需要多少個(gè)bit呢粥血,capacity/8+1,右移3位相當(dāng)于除以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后,那個(gè)位置自然就是1酿箭,然后和以前的數(shù)據(jù)做|复亏,這樣,那個(gè)位置就替換成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后缔御,那個(gè)位置自然就是1,然后和以前的數(shù)據(jù)做&械巡,判斷是否為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后刹淌,那個(gè)位置自然就是1,然后對(duì)取反讥耗,再與當(dāng)前值做&有勾,即可清除當(dāng)前的位置了.
        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);
    }
}

轉(zhuǎn)自:http://www.cnblogs.com/wuhuangdi/p/4126752.html#3074215

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市古程,隨后出現(xiàn)的幾起案子蔼卡,更是在濱河造成了極大的恐慌,老刑警劉巖挣磨,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雇逞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡茁裙,警方通過(guò)查閱死者的電腦和手機(jī)塘砸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晤锥,“玉大人掉蔬,你說(shuō)我怎么就攤上這事》” “怎么了女轿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)壕翩。 經(jīng)常有香客問(wèn)我蛉迹,道長(zhǎng),這世上最難降的妖魔是什么放妈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任北救,我火速辦了婚禮,結(jié)果婚禮上大猛,老公的妹妹穿的比我還像新娘扭倾。我一直安慰自己,他們只是感情好挽绩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布膛壹。 她就那樣靜靜地躺著,像睡著了一般唉堪。 火紅的嫁衣襯著肌膚如雪模聋。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天唠亚,我揣著相機(jī)與錄音链方,去河邊找鬼。 笑死灶搜,一個(gè)胖子當(dāng)著我的面吹牛祟蚀,可吹牛的內(nèi)容都是我干的工窍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼前酿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼患雏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起罢维,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤淹仑,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后肺孵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體匀借,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年平窘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吓肋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瑰艘,死狀恐怖蓬坡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磅叛,我是刑警寧澤屑咳,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站弊琴,受9級(jí)特大地震影響兆龙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敲董,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一紫皇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腋寨,春花似錦聪铺、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至查刻,卻和暖如春键兜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穗泵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工普气, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佃延。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓现诀,卻偏偏與公主長(zhǎng)得像夷磕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仔沿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354