0 超大集合去重
在数学上把一个集合不重复元素的个数称为集合的基数(cardinality
,也有叫做势),这类问题可以称为基数统计问题.
典型的需求是:
- 统计一个月内某App 的DAU ,MAU
- 统计某个网页UV
容易想到的思路:
-
java set
假如有个1亿个不重复的元素,每个4个字节,则内存开销 400M
-
BitMap
位图不保存实际使用的元素,只用 1bit 标识某个元素是否出现过。位图占用的内存和元素的值域有关,因为我们需要把值域映射到这个大的比特数组上。假设元素的值域是 [1,1亿],那么采用位图需要的内存就是 100000000∗1bit / 8 ≈12MB 。该方法也能够精确的计算出不重复元素的数量,比起Set来说,内存占用确实减少很多,但是如果需要统计上千个模块或者业务的数据,那么内存消耗依然很大
-
布隆过滤器(
bloom filter
)类似于位图,也是一个大的bit数组,存储的数据通过多个哈希函数计算,映射到比特数组的多个bit中,进而判断一个元素是否在集合中。布隆过滤器具有一定的误判率,占用的内存比位图略小,和误判率有关,误判率越低,需要的内存越大
-
hyperLogLog (HLL)
HyperLogLog Counting
算法以损失一定准确性为代价,能够使用极少的内存统计集合的基数,常常被用于统计产品的日活、月活,独立访客数等等场景。在Redis中也支持HyperLogLog数据结构,并且对内存的使用做了一些优化
1 分享一个国外大学的学习数据结构的网址
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html