cardinality() 是 bitset 中最直接可靠的统计方法,返回实际置为 1 的位总数,时间复杂度近 o(1),线程安全读,结果确定无副作用,不依赖 length(),适用判断非空、集合比较、缓冲区预分配及基数对比等场景。

cardinality() 是 BitSet 中最直接、最可靠的统计方法,它返回当前位集中实际被置为 1 的位的总数,也就是“已激活元素个数”。它不关心位索引多大、中间是否稀疏、数组是否扩容,只数真正为 1 的位。
为什么 cardinality() 比手动遍历更稳
它内部使用 JVM 优化的位计数逻辑(如调用 CPU 的 POPCNT 指令),时间复杂度接近 O(1) —— 实际取决于底层 long 数组长度,但远优于逐个 get(i) 判断。更重要的是:它结果确定、无副作用、线程安全读(只要没同时写)。
- 即使 BitSet 中设置了第 0 位和第 1000000 位,
cardinality()仍准确返回2 - 对空 BitSet(全 0),始终返回
0,无需判空 - 不受
length()干扰:length()返回最高置位索引 + 1,可能为 1000001,但那不代表有那么多 1
cardinality() 和 nextSetBit() 的典型配合
当你既要获知总数,又要遍历所有置位索引时,两者组合既高效又安全:
- 先调
int count = bs.cardinality();预分配固定大小容器(如int[] indices = new int[count];) - 再用
nextSetBit()循环填值,确保不越界、不遗漏、不重复扫描零位 - 最后还可校验:
idx == count表示遍历完整,避免因并发修改导致漏位
注意几个常见误区
别把 cardinality() 和其他概念混淆:
- ≠
size()或length():后两者反映内存布局或索引范围,不是元素数量 - ≠
toByteArray().length * 8:字节数组会截断高位零字节,结果偏小;且未设置的高位不会体现在数组里 - ≠ 手动循环
for (int i = 0; i :效率低、逻辑错(遍历了大量 false 位)
适用场景推荐
以下情况优先用 cardinality():
- 判断是否“至少有一个位被设置”——比
!bs.isEmpty()更通用(Java BitSet 无 isEmpty,可用bs.cardinality() > 0) - 做集合大小比较,比如筛选出活跃用户数最多的分组
- 作为批量处理的预估依据,例如分配缓冲区、初始化结果数组
- 配合交/并/差集方法(如
IntersectionCardinality)做快速基数对比,不构造新 BitSet










