標籤:電腦 序列 解決 長度 利用 題解 關係 [] 索引
問題提出:M(如10億)個int整數,只有其中N個數重複出現過,讀取到記憶體中並將重複的整數刪除。
問題分析:我們肯定會先想到在電腦記憶體中開闢M個int整型資料數組,來one bye one讀取M個int類型數組, 然後在一一比對數值,最後將重複資料的去掉。當然這在處理小規模資料是可行的。
我們 考慮大資料的情況:例如在java語言下,對10億個int類型資料排重。
java中一個 int 類型在記憶體中佔4 byte。那麼10億個int類型資料共需要開闢10 ^ 9次方 *4 byte ≈ 4GB 的連續記憶體空間。以 32 位作業系統電腦為例,最大支援記憶體為 4G, 可用記憶體更是小於4G。所以上述方法在處理大資料時根本行不通。
思維轉化:既然我們不能為所有 int 類型的資料開闢 int 類型數組,那麼可以採取更小的資料類型來讀取緩衝 int 類型資料。考慮到電腦內部處理的資料都是 01 序列的bit,那麼我們是否可以用 1bit 來表示一個 int 類型資料。
位映射的引出:使用較小的資料類型指代較大的資料類型。如上所說的問題,我們可以用1個 bit
來對應一個int 整數。假如對應的 int 類型的資料存在,就將其對應的 bit 賦值為1,否則,賦值為0(boolean類型)。java中 int 範圍為 -2^31 到 2^31-1. 那麼所有可能的數值組成的長度為2^32. 對應的 bit 長度也為 2^32. 那麼可以用這樣處理之後只需要開闢2^32 bit = 2^29 byte = 512M 大小的 記憶體空間 。顯然,這樣處理就能滿足要求了,雖然對記憶體的消耗也不太小。
問題解決方案: 首先定義如的int - byte 映射關係,當然,映射關係可以自訂。但前提要保證你的數組上下標不能越界。
但如上定義的bit[]數組顯然在電腦中是不存在的,所我們需要將其轉化為 java 中的一個基礎資料型別 (Elementary Data Type)儲存。顯然,byte[] 是最好的選擇。
將其轉化為byte[] 數組方案:
自訂的映射關係表,每個bit對應一個 int 數值,鄙人將 int 的最大值,最小值與數組的最大最小索引相對應。從可以看出來 int 數值與bit索引相差 2^31次方。當然,你也可以定義其他的映射關係,只是注意不要發生數組越界的情況。由於最大值可能是2^32,故用long接收。
long bitIndex = num + (1l << 31);
計算在轉化為byte[]數組的索引,由於上面定義的bitIndex 索引是非負數,故無需引入位元運算去符號。
int index = (int) (bitIndex / 8);
計算bitIndex 在byte[]數組索引index 中的具體位置。
int innerIndex = (int) (bitIndex % 8);
引入位元運算將byte[]數組索引index 的各個位按權值相加
dataBytes[index] = (byte) (dataBytes[index] | (1 << innerIndex));
這樣就解決了整個大資料讀取排重的問題。
利用BitMap進行大資料排序去重