大数据的处理算法——BitMap算法

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

大数据的处理算法——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算法,我就和看到宝一样。这个算法的优越性不言而喻了,以后编程中可以多多利用,故此记录下来!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值