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 位图 ✅
允许误判 布隆过滤器 ✅
相关推荐
JavaGuide2 小时前
京东零售后端一二面,附参考答案!
java·后端
开始学java2 小时前
ArrayList容器类
后端
Lear2 小时前
【JavaSE】反射与注解:深入剖析Java动态编程与案例实现
后端
Lear2 小时前
【JavaSE】Stream流:让集合操作变得优雅而高效
后端
IT_陈寒3 小时前
Redis性能提升50%的7个关键配置:从慢查询优化到内存碎片整理实战指南
前端·人工智能·后端
程序员岳焱3 小时前
Java 调用 DeepSeek API 的 8 个高频坑
java·人工智能·后端
汝生淮南吾在北3 小时前
SpringBoot+Vue非遗文化宣传网站
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
程序员爱钓鱼3 小时前
Node.js 编程实战:自定义模块与包发布全流程解析
后端·node.js·trae
武藤一雄4 小时前
C# Prism框架详解
开发语言·后端·微软·c#·.net·wpf