1. 程式人生 > >Java之大數據位圖法(無重復排序,重復排序,去重復排序,數據壓縮)

Java之大數據位圖法(無重復排序,重復排序,去重復排序,數據壓縮)

align system 容器類 底層 修改 歸並排序 概念 ppr long

大數據位圖法(無重復排序,重復排序,去重復排序,數據壓縮)之Java實現

位圖法介紹

位圖的基本概念是用一個位(bit)來標記某個數據的存放狀態,由於采用了位為單位來存放數據,所以節省了大量的空間。舉個具體的例子,在Java中一般一個int數字要占用32位,如果能用一位就表示這個數,就可以縮減大量的存儲空間。一般把這種方法稱為位圖法,即Bitmap。

位圖法比較適合於判斷是否存在這樣的問題,元素的狀態比較少,元素的個數比較多的情況之下。那麽具體咋麽做呢,這樣,非常簡單明了就是,2.5億個整數裏面,我維護一個長度等於最大整數值得字符串,每個整數是否存在我就在該整數對應的位置置為1,比如,有{2, 4, 5, 6, 67, 5}這麽幾個整數,我維護一個 00…0000 67位的字符串。但是,如果你不知道整數的最大值,你至少需要一個長度2^32的字符串,因為整數的最大值就是2^32,(int占4個字節,因此是32位),那這就最少是512M內存,從char的長度算內存會算吧,直接、最大整數/8*2^20 就是M的單位。那這麽說來就可以理解位圖法了。

BitSet

正因為位圖運算在空間方面的優越性,很多語言都有直接對它的支持。如在C++的STL庫中就有一個bitset容器。而在Java中,在java.util包下也有一個BitSet類用來實現位圖運算。此類實現了一個按需增長的位向量。BitSet的每一位都由一個boolean值來表示。用非負的整數將BitSet的位編入索引,可以對每個編入索引的位進行測試、設置或者清除。通過邏輯與、邏輯或和邏輯異或操作,可以使用一個BitSet修改另一個BitSet的內容。

需要註意的是BitSet底層實現是通過一個long數組來保存數據的,也就是說它增長的最小單位是一個long所占的邏輯位,即64位。但如果不是對存儲區空間有極致的要求,而且對自己的基本功非常有信心,不建議自己去實現一個跟BitSet類似的類來實現相關的功能。因為jdk中的類都是極精簡並做過合理優化的,BitSet類比較長。

無重復排序

java JDK裏面容器類的排序算法使用的主要是插入排序和歸並排序,可能不同版本的實現有所不同,關鍵代碼如下:

 1 /**
 2      * Performs a sort on the section of the array between the given indices
 3      * using a mergesort with exponential search algorithm (in which the merge
 4      * is performed by exponential search). n*log(n) performance is guaranteed
5 * and in the average case it will be faster then any mergesort in which the 6 * merge is performed by linear search. 7 * 8 * @param in - 9 * the array for sorting. 10 * @param out - 11 * the result, sorted array. 12 * @param start 13 * the start index 14 * @param end 15 * the end index + 1 16 */ 17 @SuppressWarnings("unchecked") 18 private static void mergeSort(Object[] in, Object[] out, int start, 19 int end) { 20 int len = end - start; 21 // use insertion sort for small arrays 22 if (len <= SIMPLE_LENGTH) { 23 for (int i = start + 1; i < end; i++) { 24 Comparable<Object> current = (Comparable<Object>) out[i]; 25 Object prev = out[i - 1]; 26 if (current.compareTo(prev) < 0) { 27 int j = i; 28 do { 29 out[j--] = prev; 30 } while (j > start 31 && current.compareTo(prev = out[j - 1]) < 0); 32 out[j] = current; 33 } 34 } 35 return; 36 } 37 int med = (end + start) >>> 1; 38 mergeSort(out, in, start, med); 39 mergeSort(out, in, med, end); 40 41 // merging 42 43 // if arrays are already sorted - no merge 44 if (((Comparable<Object>) in[med - 1]).compareTo(in[med]) <= 0) { 45 System.arraycopy(in, start, out, start, len); 46 return; 47 } 48 int r = med, i = start; 49 50 // use merging with exponential search 51 do { 52 Comparable<Object> fromVal = (Comparable<Object>) in[start]; 53 Comparable<Object> rVal = (Comparable<Object>) in[r]; 54 if (fromVal.compareTo(rVal) <= 0) { 55 int l_1 = find(in, rVal, -1, start + 1, med - 1); 56 int toCopy = l_1 - start + 1; 57 System.arraycopy(in, start, out, i, toCopy); 58 i += toCopy; 59 out[i++] = rVal; 60 r++; 61 start = l_1 + 1; 62 } else { 63 int r_1 = find(in, fromVal, 0, r + 1, end - 1); 64 int toCopy = r_1 - r + 1; 65 System.arraycopy(in, r, out, i, toCopy); 66 i += toCopy; 67 out[i++] = fromVal; 68 start++; 69 r = r_1 + 1; 70 } 71 } while ((end - r) > 0 && (med - start) > 0); 72 73 // copy rest of array 74 if ((end - r) <= 0) { 75 System.arraycopy(in, start, out, i, med - start); 76 } else { 77 System.arraycopy(in, r, out, i, end - r); 78 } 79 }

下面我們說下位圖法排序的思路:其實思路開篇已經交代,為了讓大家更容易理解,我將通過舉例的方式進一步闡明,假設我們有一個不重復的整型序

Java之大數據位圖法(無重復排序,重復排序,去重復排序,數據壓縮)