BitMap的簡單實現

Bitmap介紹

bitmap是很有用的結構。所謂的bitmap就是用一個bit位來標記某個元素,而數組下標是該元素。

bitmap優勢

bitmap經常用在大數據的題中,比如10億個int類型的數,如果用int數組存儲的話,那麼需要大約4G內存,浪費內存。如果用bitmap解決,就比較方便。bitmap可以用int來模擬,也可以用byte來模擬,它只是邏輯上的概念,在java語言中寫不出來,我們採用byte。一個byte佔8個bit,如果每一個bit的值是有或者沒有,即1或0,則如下圖所示:

bitmap Java代碼實現

第一步:構建特定長度的byte數組(new byte[capacity/8 + 1]),其中capacity爲整數數組長度(如:10億個數字等)

byte[] bits = new byte[getIndex(n) + 1];

第二步:計算數字num在byte[]中的位置(num/8和num >> 3一樣),也就是說num在byte[k],算這個k是幾

    /**
     * num/8得到byte[]的index
     * @param num
     * @return
     */
    public int getIndex(int num){
        return num >> 3;
    }

第三步:計算數字num在byte[index]中的位置,就是在byte[index]的第幾位,每個byte有8位(num % 8)

    /**
     * num%8得到在byte[index]的位置
     * @param num
     * @return
     */
    public int getPosition(int num){
        return num & 0x07;
    }

第四步:將所在位置從0變成1,其它位置不變

    /**
     * 標記指定數字(num)在bitmap中的值,標記其已經出現過
     * 將1左移position後,那個位置自然就是1,然後和以前的數據做|,這樣,那個位置就替換成1了
     * @param bits
     * @param num
     */
    public void add(byte[] bits, int num){
        bits[getIndex(num)] |= 1 << getPosition(num);
    }

解釋如下圖:

第五步:判斷指定數字num是否存在

    /**
     * 判斷指定數字num是否存在<br/>
     * 將1左移position後,那個位置自然就是1,然後和以前的數據做&,判斷是否爲0即可
     * @param bits
     * @param num
     * @return
     */
    public boolean contains(byte[] bits, int num){
        return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;
    }

第六步:重置某一數字對應在bitmap中的值

    /**
     * 重置某一數字對應在bitmap中的值<br/>
     * 對1進行左移,然後取反,最後與byte[index]作與操作。
     * @param bits
     * @param num
     */
    public void clear(byte[] bits, int num){
        bits[getIndex(num)] &= ~(1 << getPosition(num));
    }

全部代碼如下:

public class Test {

    /**
     * 創建bitmap數組
     */
    public byte[] create(int n){
        byte[] bits = new byte[getIndex(n) + 1];
        
        for(int i = 0; i < n; i++){
            add(bits, i);
        }
        
        System.out.println(contains(bits, 11));
        
        int index = 1;
        for(byte bit : bits){
            System.out.println("-------" + index++ + "-------");
            showByte(bit);

        }
        
        return bits;
    }
    
    /**
     * 標記指定數字(num)在bitmap中的值,標記其已經出現過<br/>
     * 將1左移position後,那個位置自然就是1,然後和以前的數據做|,這樣,那個位置就替換成1了
     * @param bits
     * @param num
     */
    public void add(byte[] bits, int num){
        bits[getIndex(num)] |= 1 << getPosition(num);
    }
    
    /**
     * 判斷指定數字num是否存在<br/>
     * 將1左移position後,那個位置自然就是1,然後和以前的數據做&,判斷是否爲0即可
     * @param bits
     * @param num
     * @return
     */
    public boolean contains(byte[] bits, int num){
        return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;
    }
    
    /**
     * num/8得到byte[]的index
     * @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 & 0x07;
    }
    
    /**
     * 重置某一數字對應在bitmap中的值<br/>
     * 對1進行左移,然後取反,最後與byte[index]作與操作。
     * @param bits
     * @param num
     */
    public void clear(byte[] bits, int num){
        bits[getIndex(num)] &= ~(1 << getPosition(num));
    }
    
    /**
     * 打印byte類型的變量<br/>
     * 將byte轉換爲一個長度爲8的byte數組,數組每個值代表bit
     */
    
    public void showByte(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();
    }
    
    public static void main(String[] args) {
        int n = 100;
        new Test().create(n);
    }
}

 

發佈了49 篇原創文章 · 獲贊 35 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章