1G内存,如何对40亿QQ号去重?

问题背景

假设我们需要对40亿个QQ号进行去重处理,但可用内存限制为1GB。常规方法(如HashSet或全量排序)在内存占用上存在明显瓶颈,因此需要设计一个兼顾内存效率和执行效率的解决方案。

核心挑战

  1. 内存限制:40亿个QQ号存储为long类型需约32GB(40亿×8字节),远超1GB内存。

  2. 去重准确性:必须保证100%准确,不能容忍误判。

  3. 执行效率:需尽量减少磁盘I/O和计算时间。

方案选型分析

方法

优点

缺点

全量排序

结果精确

内存不足,磁盘I/O高

布隆过滤器

内存效率高

存在误判,不适用

位图法

查询效率O(1)

依赖号码分布范围

分治法内存可控需多次磁盘I/O

结论:分治法(Hash分片+内存去重)是唯一可行方案。
思考:如果QQ号范围已知,如何进一步优化内存?欢迎在评论区分享你的想法!

分治法实现步骤

1. 计算分片数量

• 内存估算:假设每个QQ号(long类型)在HashSet中占用20字节(包含对象开销),1GB内存可存储约5千万个QQ号。
• 分片数40亿 / 5千万 = 80,建议分片数为100以留出冗余。

2. 哈希分片写入文件

// 使用取模哈希分片到100个文件
public void shardQQNumbers(String inputFile, int shardCount) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(inputFile));
    BufferedWriter[] writers = new BufferedWriter[shardCount];
    for (int i = 0; i < shardCount; i++) {
        writers[i] = new BufferedWriter(new FileWriter("shard_" + i + ".txt"));
    }
    String line;
    while ((line = reader.readLine()) != null) {
        long qq = Long.parseLong(line);
        int shardId = (int) (qq % shardCount); // 简单哈希函数
        writers[shardId].write(line + "\n");
    }
    // 关闭所有writer和reader
}

3. 逐个分片去重

public void deduplicateShard(int shardId) throws IOException {
    Set<Long> uniqueQQs = new HashSet<>();
    BufferedReader reader = new BufferedReader(new FileReader("shard_" + shardId + ".txt"));
    BufferedWriter writer = new BufferedWriter(new FileWriter("dedup_" + shardId + ".txt"));
    String line;
    while ((line = reader.readLine()) != null) {
        long qq = Long.parseLong(line);
        if (uniqueQQs.add(qq)) { // 自动去重
            writer.write(line + "\n");
        }
    }
    // 关闭reader和writer
}

4. 合并结果

将所有dedup_*.txt合并为最终文件,因相同QQ号必在同一分片,无需二次去重。

优化策略

  1. 并行处理分片:利用多线程同时处理多个分片文件。

  2. 压缩中间文件:使用GZIP压缩分片文件,减少磁盘占用。

  3. 内存优化:改用long数组+位操作替代HashSet(需号码范围已知)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值