假如要表示4个int数字:1,2,5,7,初步估计内存占用4 * 4byte(32bit) = 16byte,如果有10亿个这样的数字,那么内存占用是:
10亿 * 4 / (102410241024)= 3.72G,这么大的数据如果做查找或者排序,内存吃不消。
看看用位图如何解决这个问题:用bit来表示数字,0代表数字不存在,1代表存在,那么一个byte就可以表示8个数字,将这些byte组成一个数组,就可以表示很多数字:
如图所示,1,2,5,7都可以放入数组的第一个byte中,即bytes[0],10放入bytes[1],22放入bytes[2]
计算数字n在的bytes数组中索引:
bytes_index(n) = n/8
(注意:整数除整数,结果还是取整,比如 3/8 = 0, 10/8 = 1, 22/8 = 2)
计算数字n在byte中的位置,取模:
position(n) = n%8,比如:5%8 = 5,22 % 8 = 6
给定byte数组及位置,反推数字大小:
bytes[2],p6 => 2 * 8 + 6 = 22
之前一个int数字占用4byte(32位),现在只需要1位即可表示。10亿个的数字所需的空间也大大减小:3.72G/32 = 119M
而且可以用多线程的方式去读取,时间复杂度是O(M/N),M是bytes[]数组的大小,N 是线程大小
基于位的逻辑运算,可以用于打标的场景,比如角色、权限等
运算符说明:
|= 或等于
1 << p 将1向左移动p个位置,这样第p位将变为1,剩余位置补零
位图进行增,删,以及是否存在的操作,都可以通过位运算进行,代码如下:
package test;
public class BitMap {
/**
* 存储数据
*/
private byte[] bytes;
/**
* 位图容量
*/
private int capacity;
public BitMap