捡田螺的小男孩 2025-06-08 08:01 广东
一个非常经典的海量数据去重问题。
分享一道网上很火的面试题:
💡传统方法,例如使用HashSet,直接存储40亿QQ号码会占用大约30GB内存,远超1GB的内存限制,因此不适用。
💡BitMap是一种高效的数据结构,它使用一个bit位来表示一个数字是否存在,从而大大节省存储空间。对于40亿QQ号码,使用BitMap只需要大约0.466GB的内存,满足内存限制。
💡使用BitMap去重的流程包括:初始化一个40亿位的BitMap;遍历所有QQ号码,将每个号码映射到BitMap的对应位置,并将该位置的bit设置为1;遍历BitMap,收集所有设置为1的位对应的QQ号码,即为去重后的QQ号码。
💡BitMap的优点在于空间效率高,操作高效,去重逻辑简单。缺点是存储空间依赖值域范围,且无法存储额外信息。
捡田螺的小男孩 2025-06-08 08:01 广东
一个非常经典的海量数据去重问题。
分享一道网上很火的面试题:
Set<Long> qqSet = new HashSet<>();
qqSet.add(qqNumber); // 自动去重
40亿 * 8字节 = 320亿字节
转化位KB 32,000,000,000 字节/1024 = 31,250,000 KB
KB转化为MB 31,250,000 KB/ 1024 ≈ 30,517.578125 MB
MB转化为GB 30,517.578125 MB/ 1024 ≈ 29.8023223876953125 GB
4,000,000,000/8 = 500,000,000
500,000,000/1024/1024/1024 ≈ 0.466GB
import java.util.*;
public class QQDeduplication {
// 位图的大小为 4,294,967,296 bits,即 0.5 GB
private static final long BITMAP_SIZE = 1L << 32; // 2^32
private static final int BYTE_SIZE = 8; // 每个字节有8位
private static List<Long> deduplicateQQNumbers(long[] qqNumbers) {
// 创建位图,使用字节数组
byte[] bitmap = new byte[(int) (BITMAP_SIZE / BYTE_SIZE)];
// 更新位图
for (long qqNumber : qqNumbers) {
if (qqNumber >= 0 && qqNumber < BITMAP_SIZE) {
// 计算字节索引和位索引
int index = (int) (qqNumber / BYTE_SIZE);
int bitPosition = (int) (qqNumber % BYTE_SIZE);
// 设置对应的位
bitmap[index] |= (1 << bitPosition);
}
}
// 收集去重后的QQ号码
List<Long> uniqueQQNumbers = new ArrayList<>();
for (int i = 0; i < bitmap.length; i++) {
for (int j = 0; j < BYTE_SIZE; j++) {
if ((bitmap[i] & (1 << j)) != 0) {
long qqNumber = (long) i * BYTE_SIZE + j;
uniqueQQNumbers.add(qqNumber);
}
}
}
return uniqueQQNumbers;
}
}
AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。
鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑