一、海量、无重复的数据排序–位图排序
适用条件:
1.只能用于整数的排序,或者可以准确映射到正整数(对象不同对应的正整数也不相同)的数据的排序。
2.不能处理重复的数据,重复的数据排序后只有一条(如果有这种需求可以在这个算法的基础上修改,给出现次数大于1的数据添加个计数器,然后存入Map中)
3.对于数据量极其大的数据处理可能还是比较占用空间,这种情况可配合多通道排序算法解决。
public class BitArray {
private int[] bits = null;
private int length;
//用于设置或者提取int类型的数据的某一位(bit)的值时使用
private final static int[] bitValue = {0x80000000,//10000000 00000000 00000000 00000000
0x40000000,//01000000 00000000 00000000 00000000
0x20000000,//00100000 00000000 00000000 00000000
0x10000000,//00010000 00000000 00000000 00000000
0x08000000,//00001000 00000000 00000000 00000000
0x04000000,//00000100 00000000 00000000 00000000
0x02000000,//00000010 00000000 00000000 00000000
0x01000000,//00000001 00000000 00000000 00000000
0x00800000,//00000000 10000000 00000000 00000000
0x00400000,//00000000 01000000 00000000 00000000
0x00200000,//00000000 00100000 00000000 00000000
0x00100000,//00000000 00010000 00000000 00000000
0x00080000,//00000000 00001000 00000000 00000000
0x00040000,//00000000 00000100 00000000 00000000
0x00020000,//00000000 00000010 00000000 00000000
0x00010000,//00000000 00000001 00000000 00000000
0x00008000,//00000000 00000000 10000000 00000000
0x00004000,//00000000 00000000 01000000 00000000
0x00002000,//00000000 00000000 00100000 00000000
0x00001000,//00000000 00000000 00010000 00000000
0x00000800,//00000000 00000000 00001000 00000000
0x00000400,//00000000 00000000 00000100 00000000
0x00000200,//00000000 00000000 00000010 00000000
0x00000100,//00000000 00000000 00000001 00000000
0x00000080,//00000000 00000000 00000000 10000000
0x00000040,//00000000 00000000 00000000 01000000
0x00000020,//00000000 00000000 00000000 00100000
0x00000010,//00000000 00000000 00000000 00010000
0x00000008,//00000000 00000000 00000000 00001000
0x00000004,//00000000 00000000 00000000 00000100
0x00000002,//00000000 00000000 00000000 00000010
0x00000001 //00000000 00000000 00000000 00000001
};
public BitArray(int length) {
if (length < 0) {
throw new IllegalArgumentException("length必须大于等于零!");
}
//Java中整型为32位,所以数组长度为位长度/32。
bits = new int[length / 32 + (length % 32 > 0 ? 1 : 0)];
this.length = length;
}
//取index位的值
public int getBit(int index) {
if (index < 0 || index > length) {
throw new IllegalArgumentException("length必须大于零小于" + length);
}
int intData = bits[index / 32];
return (intData & bitValue[index % 32]) >>> (32 - index % 32 - 1);
}
//设置index位的值,只能为0或者1
public void setBit(int index, int value) {
if (index < 0 || index > length) {
throw new IllegalArgumentException("length必须大于零小于" + length);
}
if (value != 1 && value != 0) {
throw new IllegalArgumentException("value必须为0或者1");
}
int intData = bits[index / 32];
if (value == 1) {
//与移位后的1进行或运算,将指定的位,置为1,注意这里的定位。
bits[index / 32] = intData | bitValue[index % 32];
} else {
//1移位到指定的位置后,取反,就是将0移动到指定的位置,
//然后和原数进行与运算,就将指定的位置为0了,因为0和任何数相与,都变位0
bits[index / 32] = intData & ~bitValue[index % 32];
}
}
public int getLength() {
return length;
}
}
public class BitArrayTest {
static BitArray bitArray = new BitArray(Utils.BIG_DATA_NUM);
static String phoneNum;
static int phoneNumAsInt;
private static long startTime;
public static void main(String[] args) throws IOException {
Utils.generateDataNoMulti();
BufferedReader bufferedReader = new BufferedReader(new FileReader(Utils.ORIGINAL_DATA_NO_MULTI_FILE_PATH));
BufferedWriter writer = new BufferedWriter(new FileWriter(Utils.ROOT_PATH + "bit_sort.txt"));
startTime = System.currentTimeMillis();
//顺序读取所有数据
while ((phoneNum = bufferedReader.readLine()) != null) {
phoneNumAsInt = Integer.parseInt(phoneNum);
bitArray.setBit(phoneNumAsInt, 1);
}
System.out.println("生成bit数组耗时:" + (System.currentTimeMillis() - startTime) + " ms ");
startTime = System.currentTimeMillis();
//遍历bit数组输出所有存在的号码
for (int i = 0; i < bitArray.getLength(); i++) {
if (bitArray.getBit(i) == 1) {
writer.write(String.valueOf(i));
writer.newLine();
}
}
writer.flush();
System.out.println("排序并输出耗时:" + (System.currentTimeMillis() - startTime) + " ms");
}
}
测试结果
数据量=100000000
生成bit数组耗时:4676 ms
排序并输出耗时:6383 ms