位图,BitSet分析

n%8 n&7

n模8意思取8的余数,将n分为8个一组,剩下不够8个的作为余数。

   00001000 8

& 00000111 7

--------------------

   00000000 0

一个数如果有8的余数必定会出现在低3位中,即1~7,都可以中低3位表示出来,所以在低3位留1,高位全0,与运算后就会保留下8的余数。

n/8等于n被分成了多少组,159/8=19(向下取整)排第159的数字被分到第19组。

n%8得到的余数代表n这个数字在那一组的组内排号,如 159%8=19 ...... 7 代表159在第19组中的第7个位置。

bitMap[index] &= (1 << getPosition(k));

有人提到以上的写法,当 byte i = (byte)(1 << 7)时会出现溢出情况,即128赋给byte时会被转成-128,因为byte范围[-128, 127]。

但这是没关系的,因为位图中只是依靠位上的0/1来表示当前位的下标的数是否存在,

无关当前位是否 -128,当一个字节的头位被置为1,10000000,在内存中它的确表示负数,

但是位图中表示第8位的数字存在。

学习以上基础知识后,其实BitSet和自己写的BitMap很像,除了BitSet写的更加全面、健壮。

其中BitSet的设置数字部分有点不同,直接将 bitIndex(就是要添加的数字)左移,

如果我添加1亿,会不会超过long的64位范围?

不会,超出后会重新回到低位开始继续左移,例如 1L

最后与该数字所在的long做 或运算。get()函数也是如此。

其实这样做和对 被添加的数字做取余运算是一样的。

 

快速去重

20亿个整数中找出不重复的整数的个数,内存不足以容纳这20亿个整数。 

首先,根据“内存空间不足以容纳这05亿个整数”我们可以快速的联想到Bit-map。下边关键的问题就是怎么设计我们的Bit-map来表示这20亿个数字的状态了。其实这个问题很简单,一个数字的状态只有三种,分别为不存在,只有一个,有重复。因此,我们只需要2bits就可以对一个数字的状态进行存储了,假设我们设定一个数字不存在为00,存在一次01,存在两次及其以上为11。那我们大概需要存储空间2G左右。

接下来的任务就是把这20亿个数字放进去(存储),如果对应的状态位为00,则将其变为01,表示存在一次;如果对应的状态位为01,则将其变为11,表示已经有一个了,即出现多次;如果为11,则对应的状态位保持不变,仍表示出现多次。

最后,统计状态位为01的个数,就得到了不重复的数字个数,时间复杂度为O(n)。

小结&回顾

Bitmap主要用于快速检索关键字状态,通常要求关键字是一个连续的序列(或者关键字是一个连续序列中的大部分), 最基本的情况,使用1bit表示一个关键字的状态(可标示两种状态),但根据需要也可以使用2bit(表示4种状态),3bit(表示8种状态)。

Bitmap的主要应用场合:表示连续(或接近连续,即大部分会出现)的关键字序列的状态(状态数/关键字个数  越小越好)。

32位机器上,对于一个整型数,比如int a=1 在内存中占32bit位,这是为了方便计算机的运算。但是对于某些应用场景而言,这属于一种巨大的浪费,因为我们可以用对应的32bit位对应存储十进制的0-31个数,而这就是Bit-map的基本思想。Bit-map算法利用这种思想处理大量数据的排序、查询以及去重。

参考文章:

Java中Bitmap的实现 - 简书 Java中Bitmap的实现

Bitmap简介 - 废物大师兄 - 博客园 很好的BitSet解析文章和布隆过滤器

Java1.8-BitSet源码分析 - 简书 Java1.8-BitSet源码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值