40亿QQ号,不超过1G内存,如何去重?

40 亿 QQ 号(64 位整数级别)内存不超过 1GB 的条件下做去重,经典可行方案只有「位图(Bitmap / BitSet) 」,甚至进阶到「布隆过滤器」。

我给你讲最可落地的几种方案,按工程可行性来排:

✅ 最优方案:Bitmap(位图,精确去重)

1. 内存计算

假设 QQ 号范围:

最大约 10~11 位数字 ,最大值约 4,000,000,0000(按 400 亿上限算)。

但常见按 40 亿(4×10⁹) 来设计: 40 亿 bit ≈ 4,000,000,000 bits = 500,000,000 bytes ≈ 477 MB

结论:
Bitmap 完全可以在 1GB 内存内精确去重

2. 核心思想

用 bit 数组来表示某个 QQ 是否出现过:

  • 位置 = QQ号
  • 值 = 0 → 未出现
  • 值 = 1 → 已出现

读取每个 QQ:

  • 如果该位为 0 → 标记为 1
  • 如果已经是 1 → 说明重复

3. Java 示例代码(可直接运行)

java 复制代码
import java.io.BufferedReader;
import java.io.FileReader;


public class QQDedupBitmap {

    // 假设最大QQ号 = 4_000_000_000
    static final long MAX_QQ = 4_000_000_000L;
    static final int BIT_PER_BYTE = 8;

    public static void main(String[] args) throws Exception {
        // 分配位图
        byte[] bitmap = new byte[(int)(MAX_QQ / BIT_PER_BYTE + 1)];

        BufferedReader br = new BufferedReader(new FileReader("/Users/longjun/Downloads/qq.txt"));
        String line;

        while ((line = br.readLine()) != null) {
            long qq = Long.parseLong(line.trim());
            long index = qq / 8;
            int offset = (int)(qq % 8);

            if ((bitmap[(int)index] & (1 << offset)) != 0) {
                // 重复
                // 你可以输出或统计
                System.out.println("重复的QQ号:" + qq);
            } else {
                bitmap[(int)index] |= (1 << offset);
            }
        }
        br.close();
        // 恢复QQ号
        recoverQQFast(bitmap);
    }

    /**
     * 快速恢复QQ号
     * @param bitmap
     */
    public static void recoverQQFast(byte[] bitmap) {
        for (int i = 0; i < bitmap.length; i++) {
            int b = bitmap[i] & 0xFF;
            while (b != 0) {
                int offset = Integer.numberOfTrailingZeros(b);
                long qq = (long) i * 8 + offset;
                System.out.println(qq);
                b &= (b - 1);
            }
        }
    }
}

如果 QQ 号范围极大(比如 10¹² 级别)

Bitmap 不现实,使用:

✅ 布隆过滤器(Bloom Filter)

特点:

特点 说明
内存占用小 比 HashSet 小 10 倍以上
误判率 存在(会把新数据误认为重复)
不会漏判 重复一定判重复

适合场景:

  • 爬虫 URL 去重
  • 用户 ID 去重
  • 海量日志去重

Java 布隆过滤器实现(精简版)

java 复制代码
import java.util.BitSet;
import java.util.zip.CRC32;

public class BloomFilter {
    private BitSet bitSet;
    private int size;

    public BloomFilter(int size) {
        this.size = size;
        this.bitSet = new BitSet(size);
    }

    private int hash(long value, int seed) {
        long h = value ^ (value >>> 16) * seed;
        return (int)(Math.abs(h) % size);
    }

    public boolean isDuplicate(long value) {
        int h1 = hash(value, 31);
        int h2 = hash(value, 131);
        int h3 = hash(value, 1313);

        if (bitSet.get(h1) && bitSet.get(h2) && bitSet.get(h3)) {
            return true;
        }
        bitSet.set(h1);
        bitSet.set(h2);
        bitSet.set(h3);
        return false;
    }
}

🚀 超大数据工程级方案

当数据根本放不下内存:

  1. 外部排序 + 归并去重
  2. Hash 分桶 -> 小文件去重
  3. Hadoop / Spark

✅ 总结一句

在「40 亿 QQ 号 + 内存不超过 1GB」这个条件下:

目标 最优方案
精确去重 Bitmap 位图 ✅
允许误判 布隆过滤器 ✅
相关推荐
凤山老林17 小时前
Spring Boot 定时任务进阶:动态 Cron 与集群防重实战
java·spring boot·后端·定时任务·集群定时任务
站大爷IP18 小时前
被 `asyncio.gather` 和 `wait` 坑惨了:异常处理的天壤之别
后端
张龙68718 小时前
Docker 镜像瘦身实战:从 1.2GB 到 128MB,我踩过的 7 个坑和一套可复制的方法论
运维·后端·docker
lizhongxuan18 小时前
工程技术:在智能体优先的世界中利用 Codex(转)
后端
程序员cxuan20 小时前
Pi + DeepSeek-v4-Flash,这用着也太爽了。
人工智能·后端·程序员
进击的程序猿~20 小时前
Go Interface源码深度解析指南
开发语言·后端·golang
qo_tn21 小时前
微信机器人-webhook技术文档_04-Docker-Compose部署与生产化配置
后端
程序员cxuan21 小时前
Claude Opus 5 的系统提示词被扒出来了
人工智能·后端·程序员
董员外21 小时前
RAG 系统进化论(十):可运营 RAG,从原型到长期运行的知识系统
人工智能·后端·设计模式
newerp21 小时前
贪心算法 — 局部最优推导全局最优
后端