BitSet 的size()方法返回的是底层存储数组的容量(以 bit 为单位),并非逻辑上“已设置”的位数;真正能反映有效数据长度的是length()方法——它返回最高置位索引 + 1(即忽略前导零后的实际位数),这对 Huffman 压缩等需要精确控制比特流边界的场景至关重要。
先说说一个常见误区:BitSet 的 size() 方法返回的是底层存储数组的容量,以 bit 为单位,而非你逻辑上“已设置”的位数。真正能反映有效数据长度的,是 length() 方法——它返回最高置位索引 + 1,也就是忽略前导零后的实际位数。这个区别,在 Huffman 压缩这类需要精确控制比特流边界的场景中,可以说是关键所在。
在 Java 里,BitSet 是处理二进制位的高效工具,但它的行为常常被误解,尤其是在压缩算法(比如 Huffman 编码)中,稍不注意就会踩坑。你遇到的问题其实很典型:调用了 new BitSet(9) 之后,bitset.size() 输出的是 64,而不是预想中的 9。这不是 bug,而是设计如此。
❓ 为什么 size() 总是返回 64、128 或更大 64 的倍数?
BitSet 的底层实现是基于 long[] 数组的,每个 long 占 64 位。当你传入 new BitSet(9),构造器只保证“能容纳索引 0 到 8 的位”,也就是最少要支持第 9 个 bit(索引 8)。既然最小的存储单元是 1 个 long(64 bits),JVM 就必须分配一个 long[1]。所以 size() 返回 64 —— 这是实际分配的内存空间大小,跟业务逻辑里所需要的“有效位长”完全是两码事。
官方文档写得很清楚:
"Creates a bit set whose initial size is large enough to explicitly represent bits with indices in the range 0 through nbits-1."
关键词是 "large enough",而不是 "exactly"。
✅ 正确获取有效位长度:使用 length()
你真正需要的不是 size(),而是 length():
BitSet bitset = new BitSet();bitset.set(0, true); // 0th bit → truebitset.set(8, true); // 8th bit → true (so highest set bit is at index 8)System.out.println(bitset.size()); // → 64 (allocated capacity)System.out.println(bitset.length()); // → 9 (logical length: 8 + 1)
length() 的定义非常简洁:最高为 true 的位索引 + 1;如果所有位都是 false,就返回 0。这正是 Huffman 编码后比特流的真实长度——你完全不需要额外存储一个原始长度字段,解压时直接用 bitset.length() 就能精确截断。
