bitmap原理以及在java中的實現


 

轉載:https://www.jianshu.com/p/e530baada558

說bitmap之前,我們要明白數字在內存中的表示,如果說byte用8個二進制位表示,即可以表示2^8 = 256個數,每個byte占8位,即每個byte占8行,在內存中這樣形象的表示:

 
 

而bitmap結構,充分利用了每一行所有的位數,它將每個位置作為一個數,那么一行就可以模擬表示出8個數。

 

Bitmap介紹

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

bitmap優勢

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


 
 

比如,當我們用 int 類型來模擬 Bitmap 時,一個 int 4個字節共 4*8 = 32位,可以表示32個數。原來10億個 int 類型的數用 int 數組需要 4G 的內存,但是我用 bitmap 只需要 4GB / 32 = 128 MB 的內存,是不是少多了。

bitmap代碼實現

第一步:構建特定長度的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); } } 

結果如圖,一共100個數:


 
 

雜談

下面是我搜集的一些關於bitmap的,有時間再看。。。
https://blog.csdn.net/a3192048/article/details/80261699

這是關於java中原生的bitmap的實現,BitSet
https://blog.csdn.net/lushuaiyin/article/details/7546144

https://blog.csdn.net/y999666/article/details/51220833

https://blog.csdn.net/xia744510124/article/details/51509285/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM