一、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));
}
