Bitmap在Java中的應用
一、40億資料排序問題
給定一個最多包含40億個隨機排列的32位整數的順序檔案,找出一個不在檔案中的32位整數(在檔案中至少缺失這樣一個數——為什麼?)。在具有足夠記憶體的情況下,如何解決該問題?(程式設計珠璣)
二、應用BitMap儲存大資料
資料的存在性可以使用bit位上的1或0來表示;一個bit具有2個值:0和1,正好可以用來表示false和true。
對於判斷“資料是否存在”的場景,我們通常使用HashMap來儲存,不過hashmap這個資料結構KEY和Value的儲存需要消耗較多的記憶體,不適合儲存較多的資料,比如上面的問題中,如果使用雜湊表,每條記錄儲存一個int型的key和一個boolean型的value,
每條至少需要4位元組,假設40億條資料全部不相同,40億條記錄佔據160億位元組,即需要16G記憶體,明顯太高。
如何減少資料佔用儲存空間可以使用位示圖解決,java.util.BitSet可以按位儲存,提供了BitMap的典型實現。
比如有一堆數字,需要儲存,source=[3,5,6,9]
用int就需要4*4個位元組。
java.util.BitSet可以存true/false。
如果用java.util.BitSet,則會少很多,其原理是:
1,先找出資料中最大值maxvalue=9
2,宣告一個BitSet bs,它的size是maxvalue+1=10
3,遍歷資料source,bs[source[i]]設定成true.
最後的值是:
(0為false;1為true)
bs [0,0,0,1,0,1,1,0,0,1]
3, 5,6, 9
這樣一個本來要int型需要佔4位元組共32位的數字現在只用了1位,這樣就省下了很大空間。
常見的應用場景是那些需要對海量資料進行一些統計工作的時候,比如日誌分析、使用者數統計等等。
如統計40億個資料中沒有出現的資料,將40億個不同資料進行排序等。
三、如何應用BitSet
BitSet實現了Vector介面,BitSet中陣列大小會隨需要增加,位的值為布林型,
bitSet內部是通過一個long[]陣列實現的,
所以初始大小為64bit,初始值均為“false”。
先看一下API中的說明
This class implements a vector of bits that grows as needed.
BitSet類實現了一個按需增長的位元向量,
Each component of the bit set has a boolean value.
每個元素都有一個boolean值,
The bits of a BitSet are indexed by nonnegative integers.
使用非負整數對每個位進行索引,
Individual indexed bits can be examined, set, or cleared.
可以對每個編入索引的位進行測試、設定或者清除。
One BitSet may be used to modify the contents of another BitSet through logical AND, logical inclusive OR, and logical exclusive OR operations.
通過邏輯與、邏輯或和邏輯異或操作,可以使用一個 BitSet 修改另一個 BitSet 的內容。
By default, all bits in the set initially have the value false.
預設情況下,set 中所有位的初始值都是 false。
Every bit set has a current size, which is the number of bits of space currently in use by the bit set. Note that the size is related to the implementation of a bit set, so it may change with implementation. The length of a bit set relates to logical length of a bit set and is defined independently of implementation.
每個位 set 都有一個當前大小,也就是該位 set 當前所用空間的位數。注意,這個大小與位 set 的實現有關,所以它可能隨實現的不同而更改。位 set 的長度與位 set 的邏輯長度有關,並且是與實現無關而定義的。
public static void main(String[] args) {
int [] array = new int [] {1,2,3,22,0,3};
BitSet bitSet = new BitSet(6);
//將陣列內容組bitmap
for(int i=0;i<array.length;i++)
{
bitSet.set(array[i], true);
}
System.out.println(bitSet.size());
System.out.println(bitSet.get(3));
}