使用bitmap進行大量數據的排序、判斷存在與否

使用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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章