大数据的处理算法——BitMap算法
首先我们来看一个问题:
如何判断一个整数是否在40亿个整数之中?
当时我看到这个问题首先想到的是利用一个map或者set进行存储(/笑哭)
但是一个整数4个字节,40亿个整数就是160亿个字节,需要16GB的内存(/惊讶)
如果分多次加载就需要利用到磁盘的IO,但是磁盘的IO读取速度远远低于内存的读取速度
所以是不可取的!!!
那么可以采用分布式的算法来实现,利用8台计算机,每台计算机2G内存,将数据分散到这8台计算机中进行处理,这样的效率就比较能够接受。
但是还有没有更好的方式呢?
有!!!
是什么?
Bitmap算法!!!
Bitmap算法
首先我们来了解一下bitmap算法是个啥?
1:Bit-Map算法又名位图算法,其原理是,使用下标代替数值或特定的意义,使用这个位为0或者1代表特性是否存在。
2:Bit-Map算法具有效率高,节省空间的特点,适用于对大量数据进行去重,查询等。
说简单点
就是咱们把每个数据的状态存在为1,不存在为0,利用bit字节来进行存储,这样大大的节约了空间!!
那么可以简单的联想到BitMap的应用领域:
排序,查找,存储一个用户的各种标签数据啊,用bitmap算法都是一种比较棒的方式。
那么回到题目:
如何判断一个整数是否在40亿个整数之中?
我们来看一段代码,当然这里我没用40亿这么大
我这里用10000000,其实也很大了(/doge)
import java.util.ArrayList;
import java.util.List;
public class BitMap {
private static final int N = 10000000;
private int[] a = new int[N/32 + 1];
/**
* 设置所在的bit位为1
* @param n
*/
public void addValue(int n) {
//int row = n / 32;
int row = n >> 5;
// >>相当于/2的n次方,<<相当于*2的n次方
a[row] |= 1 << (n & 0x1F);
// |=是相当于a 和=后面的值做或运算然后赋值给a
// 0x在计算机中代表16进制,F代表16 1F = 1*F + F = 32
// << >> 实际为java中的移位运算符 >> 向左移动一位即等于乘以2
// << 为向右移动即等于除以2
}
/**
* 判断所在bit位是否为1
* @param n
* @return
*/
public boolean exits(int n) {
int row = n >> 5;
return (a[row] & (1 << (n & 0x1F))) != 0;
}
public void display(int row) {
System.out.println("bitMap位图展示");
for(int i = 0; i < row; i++) {
List<Integer> list = new ArrayList<Integer>();
int temp = a[i];
for(int j = 0; j < 32; j++) {
list.add(temp & 1);
temp >>= 1;
}
System.out.println("a["+i+"]" + list);
}
}
public static void main(String[] args) {
int[] num = {1,5,30,32,64,56,159,120,21,17,35,45};
BitMap map = new BitMap();
for(int i = 0; i < num.length; i++) {
map.addValue(num[i]);
}
int temp = 120;
if(map.exits(temp)) {
System.out.println("temp:" + temp + "has already exists");
}
int temp2 = 131;
if(map.exits(temp2)) {
System.out.println("temp2:" + temp2 + " has already exists");
}else {
System.out.println("temp2:" + temp2 + " not has already exists");
}
map.display(5);
}
}
运行结果:
temp: 120 has already exists
temp2: 131 not has already exists
bitMap位图展示
a[0][0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
a[1][1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
a[2][1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
a[3][0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
a[4][0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
要想实现这个bitMap算法,首先我们要想明白两点:
1.十进制如何转化为对应数组a中的下标
解决办法:
十进制数0-31,对应在数组a[0]中,32-63对应在数组a[1]中,64-95对应在数组a[2]中………,使用
数学归纳分析得出结论:对于一个十进制数n,其在数组a中的下标为:a[n/32]
2十进制对在对应a[i]中的下标
例如十进制数1在a[0]的下标为1,十进制数31在a[0]中下标为31,十进制数32在a[1]中下标为0。 在
十进制0-31就对应0-31,而32-63则对应也是0-31,即给定一个数n可以通过模32求得在对应数组a[i]
中的下标。
那么这里就不能不碰到java中的位运算了
然后有关Java的位运算,我在注释里面写的很详细,可以仔细去看下(/doge)
当然
a[row] |= 1 << (n & 0x1F);
// |=是相当于a 和=后面的值做或运算然后赋值给a
// 0x在计算机中代表16进制,F代表16 1F = 1*F + F = 32
这里是通过移位的方式来置1的
结语
当我看到bitmap算法,我就和看到宝一样。这个算法的优越性不言而喻了,以后编程中可以多多利用,故此记录下来!

博客介绍了如何使用Bitmap算法解决在大量数据中判断一个整数是否存在的问题。Bitmap算法利用位操作,将数据状态存储为0或1,节省空间且效率高,适用于数据去重和查询。通过Java代码示例解释了如何将十进制转化为数组下标,并运用位运算进行操作。最后强调了Bitmap算法在大数据处理中的优势。

2400

被折叠的 条评论
为什么被折叠?



