位图(bitmap)的原理是用一个位来表示一个数字(准确说是用数组下标和一个位来表示)。
java中一个int类型占4Byte,32字节。如果我们使用位图来存储数据。那么一个int类型就可以存储32个数据。
//假设我们要存储20亿整数
private static final int N = 2000000000;
//如果按照普通数组方式存储 我们需要开辟一个new int[N]的空间
//但是使用位图 我们使用的空间是原来的 1/32
private int[] a = new int[N / 32 + 1];
public int[] getA() {
return a;
}
/**
* row = n / 32 求整数n在数组a中的下标 如 n = 7 那么它在数组下标为0的位置
* n=32(32/32=1) 那么它在数组下标为1的位置
* a[row] |= 1 << (n & 0x1F) 这个语句是求n在对应下标的具体位置
* n & 0x1F 表示将n和31求与 如n = 7 那么7 & 0x1F = 7 表示在0中的位置为7
* 如n = 32 那么32 & 0x1F = 0 表示在0中的位置为0
* 1 << (n & 0x1F) n % 32
*
* @param n
*/
public void addValue(int n) {
int row = n >> 5;
//相当于 n % 32 求十进制数在数组a[i]中的下标
a[row] |= 1 << (n & 0x1F);
}
// 判断所在的bit为是否为1
public boolean exists(int n) {
int row = n >> 5;
return (a[row] & (1 << (n & 0x1F))) == 1;
}
文件去重测试
/**
* 随机输入200万整数
* 存到value.txt中
* @throws IOException
*/
public void randomValues() throws IOException {
FileWriter writer = null;
File file = new File("value.txt");
if (!file.exists()) {
file.createNewFile();
}
writer = new FileWriter(file);
for (int i = 0; i < 2000000; i++) {
int a = (int) (Math.random() * 100000000);
writer.write(a + System.getProperty("line.separator"));
}
writer.flush();
}
/**
* 去重读到 value1.txt中
* @throws IOException
*/
public void reValues() throws IOException {
File file = new File("value.txt");
File file1 = new File("value1.txt");
FileWriter writer = new FileWriter(file1);
if (!file1.exists()) {
file1.createNewFile();
}
BufferedReader reader = new BufferedReader(new FileReader(file));
String string = null;
int count = 0;
while ((string = reader.readLine()) != null) {
int temp = Integer.parseInt(string);
if (!exists(temp)) {
count++;
this.addValue(temp);
writer.write(temp + System.getProperty("line.separator"));
}
}
writer.flush();
System.out.println(count);
}