问题:40亿QQ号, 1G内存,怎么去重
方式1:使用bitmap进行海量数据去重
如果我们硬算,从1到40亿 和40亿个QQ号做比对,然后有的就存储下来,没有就放弃,第一个性能很差,第二不满足1G内存的要求。
这里我们使用bitmap进行海量数据去重的方式。
什么是bitmap算法?
其实很简单,假如我们有4个数要去重,我们申请一个4个bit位的数组,如下图所示:
假如放置1和4这两位整数,那么就把1和4这个位置的bit位置为1.我们需要拿出来不重复的数 只要拿bit位为1的的位置就是我们需要的不重复的数。
同理40亿个QQ号我们就搞一个40亿个bit位的bitmap.遍历这个bitmap就能拿出来所有不重复的qq号
我们使用的内存空间=4000000000*1/8/1024/1024=476M 够用了
bitmap算法的优势在于它可以非常高效地进行集合运算。具体来说,如果我们需要对一个集合进行多次交集、并集、差集等操作,使用 BitMap 可以将这些操作的时间复杂度降低到 O(1) 级别,而传统的集合实现则需要 O(n) 的时间复杂度,其中 n 是集合的大小。
此外,BitMap 还可以节省存储空间。对于一个只包含 0 和 1 的集合,我们可以使用一个比特位来表示一个元素是否在集合中,这样可以将集合的存储空间降低到原来的 1/8 左右。
所以,位图最大的好处就是节省空间
位图有很多种用途,特别适合用在去重、排序等场景中,著名的布隆过滤器就是基于位图实现的
但是位图也有着一定的限制,那就是他只能表示0和1,无法存储其他的数字。
所以BitMap只适合这种能表示ture or false的场景。
其次,BitMap 只适用于值域比较小的集合,如果值过大,bitmap占用的一块非常大的连续的存储空间,也是非常不现实的。
最后,BitMap 不支持删除操作,因为删除一个元素需要将对应的比特位设置为 0,这可能会影响到其他元素的状态。
布隆过滤器
我们前面解释了bitmap算法,我们为了减少bitmap内存的开销可以将我们要过滤的值计算出hash,然后按照bitmap的存储进行存储。就是说我们判断的是该值的hash是否存在。比如说我们要对汉语的词语进行过滤,我们也没有办法穷举。那么我们可以把词语的hash用bitmap判断是否出现过。
这样一来会节省大量的存储空间,第二解决一些无法穷举的场景
同时这个算法会带来另外一个问题,就是误判的问题,因为我们把上面算法的数值改成hash,就有冲突的可能。
比如说 'AAA'的hash=1 ‘BBB’的hash=1 那么我们之前防止AAA的hash进bitmap 再对BBB进行判断,因为他的hash也是1.所以认为BBB也存在过。
布隆过滤器的应用场景
1、网页爬虫:爬虫程序可以使用布隆过滤器来过滤掉已经爬取过的网页,避免重复爬取和浪费资源。
2、缓存系统:缓存系统可以使用布隆过滤器来判断一个查询是否可能存在于缓存中,从而减少查询缓存的次数,提高查询效率。布隆过滤器也经常用来解决缓存穿透的问题。
3、分布式系统:在分布式系统中,可以使用布隆过滤器来判断一个元素是否存在于分布式缓存中,避免在所有节点上进行查询,减少网络负载。
4、垃圾邮件过滤:布隆过滤器可以用于判断一个邮件地址是否在垃圾邮件列表中,从而过滤掉垃圾邮件。
5、黑名单过滤:布隆过滤器可以用于判断一个IP地址或手机号码是否在黑名单中,从而阻止恶意请求。