简介:面对40亿条账号去重、内存仅1GB的约束,单机哈希表无法承载。本文从基数估算、位图与哈希分片两条路线出发,给出可落地的内存预算、分片策略、冲突处理与多轮合并流程,并附伪代码与参数推导,帮助读者在面试与生产环境中快速判断方案边界与取舍。
“40亿个QQ号,1GB内存如何去重”是一道典型的分布式/大数据处理入门题。它的核心矛盾在于:
因此,任何试图用普通哈希表(HashSet)直接存放全部数据的方案,都会因内存溢出而失败。必须借助外部排序、位图、哈希分片或概率数据结构等思路,将“大集合”拆解为“可分批处理的小集合”。
QQ号通常为5~12位数字,实际业务中并非所有数字都被占用。若按最大值约10^12估算,直接使用位图需要:
10^12 bit = 125 GB
远超1GB。因此,不能直接对全量QQ号做位图。但如果能确认QQ号的最大值在40亿左右(例如实际有效账号集中在某个区间),则位图大小可压缩到:
40亿 bit = 500 MB
加上控制开销,1GB内存可以容纳。所以第一步应是:确认QQ号的数值范围。若范围可控,位图是极优方案;若范围不可控,则走哈希分片。
用一个比特位表示一个QQ号是否存在。若QQ号最大值为N,则需N+1个比特。40亿个账号若最大号约为40亿,则需约500MB。
(maxQQ + 1) / 8 字节的字节数组;伪代码:
byte[] bitmap = new byte[(MAX_QQ + 1) / 8 + 1];for (long qq : allQQ) {int byteIndex = (int)(qq / 8);int bitIndex = (int)(qq % 8);byte mask = (byte)(1 << bitIndex);if ((bitmap[byteIndex] & mask) == 0) {bitmap[byteIndex] |= mask;// 输出 qq 作为不重复项output(qq);}}
当QQ号范围不确定或最大值极大时,位图不可行。此时采用哈希分片:将40亿条数据按哈希值分成若干小文件,保证每个小文件都能在内存中独立去重。
假设内存1GB,单个哈希表最多容纳约5000万条(考虑对象开销,实际可能更少)。将40亿条分成100片,每片约4000万条,内存可控。
分片规则:
fileIndex = hash(qq) % 100
遍历原始数据,将每个QQ号写入对应的小文件。每个小文件约4000万条,远小于1GB。
对每个小文件,加载到内存HashSet中,去重后输出。由于分片保证相同QQ号一定在同一文件,因此不会跨文件重复。
若单个小文件仍超过内存,可继续二次分片,直到每个子文件都能装入内存。最终将所有去重结果合并。
伪代码:
// 第一轮:分片for (long qq : allQQ) {int shard = (int)(hash(qq) % SHARD_COUNT);writeToFile(shard, qq);}// 第二轮:逐片去重for (int i = 0; i < SHARD_COUNT; i++) {Set<Long> set = new HashSet<>();for (long qq : readFile(i)) {if (set.add(qq)) {// 首次出现}}output(set);}
另一种经典思路是外部排序:
该方案优点是不依赖哈希分片,缺点是排序开销大,且需要磁盘空间至少为原始数据的两倍。
若业务允许近似去重(例如仅需估算不重复数量,或允许极低误判率),可使用布隆过滤器(Bloom Filter):
例如,1GB内存可支持约80亿个元素的布隆过滤器(误判率约1%)。但注意:布隆过滤器只能判断“可能存在”,不能直接输出精确去重结果。若需精确去重,仍需结合分片或排序。
| 方案 | 内存需求 | 精确性 | 磁盘IO | 适用场景 |
|---|---|---|---|---|
| 位图 | 取决于最大值 | 精确 | 无 | QQ号范围可控 |
| 哈希分片 | 可控 | 精确 | 高 | 通用,范围不可控 |
| 外部排序 | 可控 | 精确 | 高 | 可接受排序开销 |
| 布隆过滤器 | 极低 | 近似 | 无 | 仅需估算或允许误判 |
面试回答建议:先确认QQ号范围。若范围在40亿以内,直接位图,500MB即可;若范围未知,采用哈希分片,分100片,每片4000万,逐片HashSet去重。若允许近似,可提布隆过滤器作为补充。
HashSet<Long>每个元素约48字节,5000万条即2.4GB,远超1GB。因此分片数应更大,或使用原始long[]+排序去重。hashCode()直接取模,应使用MurmurHash或FNV等均匀哈希。40亿QQ号去重、1GB内存的核心是分而治之:要么用位图压缩表示,要么用哈希分片将大集合拆小,要么用外部排序化随机为有序。实际选型取决于QQ号范围、精确性要求和磁盘IO成本。掌握这套分析框架,不仅能应对面试,也能在日志去重、用户画像、风控名单等场景中快速落地。