40亿QQ号,只有1G内存,怎么存储和去重?

这是一道面试经典考题,实际上在项目中用处也非常大。

分析

QQ号都是整数,先假设使用 int 存储,一个 int 占 4 个字节,简单计算 40亿 * 4 / 1024 / 1024 / 1024 = 14.9 GB,大概需要 15GB 左右的空间才能存的下,用 long 和 Integer 就更多了,差不多分别是 int 的 2 倍和 4 倍空间需求。

这么大的内存占用显然不符合面试官的要求。

使用 int 存储,0 和 1000000000 都是一样的 4 byte,那大部分的空间不都妥妥的浪费了,有没有更高效一点的结构呢?

聪明的你一定想到了,对数字来说没必要全量存储,可以用一串二进制码来表示,所在位是 0 表示不存在该数字,所在位是 1 表示存在该数字,比如 1010 从右至左就表示 1,3 两个数字,这样每个数字就只占用 1 bit,8 bit 等于 1 字节,存下 40 亿QQ号也只需要 40亿 / 8 / 1024 / 1024 = 476.83 MB

恭喜你,发明了位图!

位图

位图(BitMap)的基本思想就是用 bit 来标示一个元素的存在与否,通常只有 0 和 1 两种值。

因为用 bit 来存储数据,所以其最大的优点就是节省空间,适用于对海量数字的存储和去重。也正因为使用位表示数字,所以对于稀疏数据来说,相对比较浪费空间,比如位图只存了 1 和 999,那么中间的第 2 位 到第 998 位都是0,相当于用 999 bit 只存了 2 个数字。

同样的道理,位图也适合数字场景。

在 Java 中,位图的具体实现是 BitSet。

BitSet 源码解析

底层结构

底层是一个 long 数组。

vbnet 复制代码
/**
 * The internal field corresponding to the serialField "bits".
 * 这个就是用来存具体二进制位图的数组,每个long有64位,所以可以存64位的二进制数字
 */
private long[] words;

索引定位

因为 long 有 64 位,所以通过 bitIndex / 64 计算应该存到数组的哪个位置上。

arduino 复制代码
/**
 * Given a bit index, return word index containing it.
 * 确定一个位应该存在数组的哪个位置上,返回数组下标
 */
private static int wordIndex(int bitIndex) {
    // 通过位运算提高效率,右移计算相当于除以2的次幂,2的6次幂就是64,这里等价 bitIndex / 64
    return bitIndex >> 6;
}

设置位

scss 复制代码
/**
 * Sets the bit at the specified index to { @code true}.
 *
 * @param bitIndex a bit index
 * @throws IndexOutOfBoundsException if the specified index is negative
 * @since JDK1.0
 */
public void set(int bitIndex) {
    if (bitIndex < 0)
        throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

    int wordIndex = wordIndex(bitIndex); // 确定索引
    expandTo(wordIndex);

    // 这一步是设置对应的二进制位为1
    words[wordIndex] |= (1L << bitIndex); // Restores invariants

    checkInvariants();
}

核心逻辑

  • 1L << bitIndex:生成一个只有指定位为 1 的掩码。
  • |=:按位或操作,确保目标位被设置为 1,其他位保持不变。

以上就是 Java BitMap 实现类 BitSet 的核心逻辑。

相关推荐
机器学习之心21 小时前
多目标鲸鱼优化算法(NSWOA),含46种测试函数和9个评价指标,MATLAB实现
算法·matlab·多目标鲸鱼优化算法·46种测试函数·9个评价指标
西阳未落1 天前
C++基础(21)——内存管理
开发语言·c++·面试
max5006001 天前
基于Meta Llama的二语习得学习者行为预测计算模型
人工智能·算法·机器学习·分类·数据挖掘·llama
ANYOLY1 天前
Redis 面试宝典
数据库·redis·面试
珍宝商店1 天前
前端老旧项目全面性能优化指南与面试攻略
前端·面试·性能优化
王哥儿聊AI1 天前
Lynx:新一代个性化视频生成模型,单图即可生成视频,重新定义身份一致性与视觉质量
人工智能·算法·安全·机器学习·音视频·软件工程
手握风云-1 天前
优选算法的寻踪契合:字符串专题
算法
闭着眼睛学算法1 天前
【华为OD机考正在更新】2025年双机位A卷真题【完全原创题解 | 详细考点分类 | 不断更新题目 | 六种主流语言Py+Java+Cpp+C+Js+Go】
java·c语言·javascript·c++·python·算法·华为od
IT古董1 天前
【第五章:计算机视觉-项目实战之目标检测实战】2.目标检测实战:中国交通标志检测-(2)中国交通标志检测数据格式转化与读取
算法·目标检测·计算机视觉
MobotStone1 天前
LLM 采样入门到进阶:理解与实践 Top-K、Top-P、温度控制
算法