BitSet位图算法如何实现海量数据清洗中的超低内存去重过滤?
- 内容介绍
- 文章标签
- 相关推荐
本文共计933个文字,预计阅读时间需要4分钟。
BitSet 不能直接用于海量数据。
BitSet.set(x) 为什么会 OOM?不是说它省内存吗
省的是有效数据所占的位空间,不是“按需分配”。BitSet 底层是 long[],调用 set(1_000_000_000) 时,它必须确保索引 10⁹ 能被容纳,即至少分配 ⌈10⁹ / 64⌉ ≈ 15.6M 个 long,约 125 MB 连续堆内存。如果最大 ID 是 10 亿但只用了 1000 个,这 125 MB 仍全量分配。
- 真实错误现象:
OutOfMemoryError: Requested array size exceeds VM limit(JVM 拒绝分配超 2GB 的数组) - 别信“能存 21 亿个 bit”——那是理论上限,实际受限于堆大小和连续内存可用性
- 若原始数据含负数(如
long类型用户 ID),直接传入set()会转成极大正数(比如-1L→18446744073709551615),瞬间触发 OOM
cardinality() 和手动计数,哪个更适合清洗流程
cardinality() 是全量扫描内部 long[] 统计 1 的个数,时间复杂度 O(n),且每次调用都重新算;而清洗任务通常边读边判重边计数,高频更新下自己维护 uniqueCount 更快也更准。
本文共计933个文字,预计阅读时间需要4分钟。
BitSet 不能直接用于海量数据。
BitSet.set(x) 为什么会 OOM?不是说它省内存吗
省的是有效数据所占的位空间,不是“按需分配”。BitSet 底层是 long[],调用 set(1_000_000_000) 时,它必须确保索引 10⁹ 能被容纳,即至少分配 ⌈10⁹ / 64⌉ ≈ 15.6M 个 long,约 125 MB 连续堆内存。如果最大 ID 是 10 亿但只用了 1000 个,这 125 MB 仍全量分配。
- 真实错误现象:
OutOfMemoryError: Requested array size exceeds VM limit(JVM 拒绝分配超 2GB 的数组) - 别信“能存 21 亿个 bit”——那是理论上限,实际受限于堆大小和连续内存可用性
- 若原始数据含负数(如
long类型用户 ID),直接传入set()会转成极大正数(比如-1L→18446744073709551615),瞬间触发 OOM
cardinality() 和手动计数,哪个更适合清洗流程
cardinality() 是全量扫描内部 long[] 统计 1 的个数,时间复杂度 O(n),且每次调用都重新算;而清洗任务通常边读边判重边计数,高频更新下自己维护 uniqueCount 更快也更准。

