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 位图 ✅
允许误判 布隆过滤器 ✅
相关推荐
行百里er7 小时前
Redis 完结篇——Redis 热点问题在 Spring Boot 项目中实战
redis·后端
高频因子挖掘机8 小时前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
孟健8 小时前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
码事漫谈9 小时前
丢得静悄悄,谈一谈 Agent 的记忆是怎么没的
后端
迪飞特科技9 小时前
智慧物业平台实战:Spring Boot 整合小程序实现报修巡检费用全流程
spring boot·后端·小程序
考虑考虑9 小时前
@JsonInclude注解使用
spring boot·后端·spring
IT_陈寒10 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信10 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
CCblandy10 小时前
HTTP 长连接 3 类故障实测:[WinError 10053]、99 个 TIME_WAIT、69 次多余握手,4 种对策怎么选
后端·python·网络协议·http·云原生·性能优化·架构
蜗牛互联网10 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python