使用bitmap進行大量資料的排序、判斷存在與否
阿新 • • 發佈:2018-12-20
使用bitmap主要是可以減少儲存空間的使用,用一個bit來儲存一個元素的狀態。當我們需要在一億個數中判斷某個數是否存在時,我們不需要將這一億個數同時放入記憶體。
排序
首先有一個bit陣列,如果我們排序的所有元素中最大的數是一億,那麼我們就需要這個陣列大小初始化為一億零一(加上0),從0排到一億,每一位bit就對應這個數,比如第6個bit位對應數字5的狀態,如果是1表示待排序中存在5,是0,,則表示待排序陣列中沒有5。當我們使用待排序陣列完成對bitmap的填充之後,只需要按位輸出存在的數就可以了。
/**
* created by tianfeng on 2018/11/9
* 使用bitmap進行排序(待排序陣列中無重複數字)
*/
public class BitmapSort {
private int maxNumber;
private int[] bitmap;
public void sort(int[] array){
for (int i = 0;i<array.length;i++){
int number = array[i];
int bit = number>>5;
int index = number&((1<<5)-1);
bitmap[ bit] |= 1<<index;
}
for (int i=0;i<bitmap.length;i++){
for (int j = 0;j<32;j++){
if ((bitmap[i]&(1<<j))!=0){
System.out.print(i*32+j+" ");
}
}
}
}
public BitmapSort(int maxNumber) {
this.maxNumber = maxNumber;
bitmap = new int[(maxNumber>>5)+1];
}
public static void main(String[] args) {
BitmapSort bitmapSort = new BitmapSort(88);
int[] array = {88,86,45,65,78,75,12,35,24,5,1,23};
bitmapSort.sort(array);
}
}
如果待排序中有重複的數字,就會只輸出一個,這個問題不知道有沒有解決的辦法,也許可以用多個位表示一個數,但多少個是個多哇。這個問題誰知道告告我嘿嘿。不過也因為bitmap的這個特點——重複的數字只出現一次,我們可以使用同樣的程式碼對一堆數字進行去重操作。
判斷一個數是否存在
一個檔案裡有一億個數,我們如何判斷88是否存在其中?簡單就是遍歷一遍,但是如果記憶體不夠呢?如果數是int型,佔4個byte,一億個數就是400M,如果十億個數呢?4個G。把四個G的數都放入記憶體,才能完成這個遍歷。如果記憶體不夠呢?我們就可以採用bitmap,記錄十億個數的狀態,我們只需要十億個bit,也就是125M。
public class IsNumberExist {
private int[] bitmap;
private int size;
private int SHIFT = 5;//2的5次方是32
public boolean isNumberExist(int number){
int bit = number>>SHIFT;
int index = number&((1<<SHIFT)-1);
return ((1<<index)&bitmap[bit])!=0;
}
public IsNumberExist(int size){
this.size = size;
bitmap = new int[(size>>SHIFT)+1];
}
public void insertDate(int number){
int bit = number>>SHIFT;
int index = number&((1<<SHIFT)-1);
bitmap[bit] = bitmap[bit]|(1<<index);
}
public void insertFromTxt(String filename){
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
String str = null;
while ((str = br.readLine())!=null){
insertDate(Integer.valueOf(str));
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
System.out.println("當前JVM所佔記憶體:"+(rt.totalMemory()-rt.freeMemory())/1024/1024+"M");
IsNumberExist tool = new IsNumberExist(1000000000);
System.out.println("當前JVM所佔記憶體:"+(rt.totalMemory()-rt.freeMemory())/1024/1024+"M");
//Date.makeNumbers(100000000);//生成一億個數到number.txt
tool.insertFromTxt("numbers.txt");//使用這個一億個數初始化bitmap的狀態
System.out.println(tool.isNumberExist(88888888));//判斷88888888是否在這個檔案中
System.out.println(tool.isNumberExist(99999999));//判斷99999999是否在這個檔案中
System.out.println(tool.isNumberExist(91725151));//判斷91725151是否在這個檔案中
}
}
生成資料的類:
public class Date {
public static boolean makeNumbers(int size){
boolean flag = true;
Random random = new Random();
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("numbers.txt"));
for (int i = 0;i<size;i++){
bw.write(String.valueOf(Math.abs(random.nextInt(size))));
bw.newLine();
}
bw.close();
} catch (IOException e) {
flag = false;
e.printStackTrace();
}
return flag;
}
}