1. 程式人生 > >使用bitmap進行大量資料的排序、判斷存在與否

使用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;
    }
}