位图(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); }