java.util.BitSet--set()不';I don’我没有按预期工作

java.util.BitSet--set()不';I don’我没有按预期工作,java,bit-manipulation,bitset,Java,Bit Manipulation,Bitset,我是否错过了一些显而易见的痛苦?还是世界上没有人真正使用java.util.BitSet 以下测试失败: @Test public void testBitSet() throws Exception { BitSet b = new BitSet(); b.set(0, true); b.set(1, false); assertEquals(2, b.length()); } 我真的不明白为什么不以长度为2、值为10的位集结束。我查看了java.util.B

我是否错过了一些显而易见的痛苦?还是世界上没有人真正使用java.util.BitSet

以下测试失败:

@Test
public void testBitSet() throws Exception {
    BitSet b = new BitSet();
    b.set(0, true);
    b.set(1, false);
    assertEquals(2, b.length());
}
我真的不明白为什么不以长度为2、值为10的位集结束。我查看了java.util.BitSet的源代码,在不经意的检查中,它似乎无法充分区分设置为false的位和从未设置为任何值的位

(请注意,在构造函数中显式设置位集的大小无效,例如:

BitSet b = new BitSet(2);
您设置的最高位(如“设置为1”)是位0。因此长度应为1

见:

公共整数长度()

返回此位集的“逻辑大小”:位集中最高的集合位加1的索引。如果该位集不包含集合位,则返回零


也许您正在寻找,但如果以特定的分辨率分配位(比如16位边界),可能会高于2位人们确实使用了
位集
;然而,他们使用它的目的并非你想要的。最好将
位集
看作是一种非常紧凑、内存效率很高的
形式,它有一个特殊的特性,就是你不能在其中放入负数

对于
位集
s,在

for (int id = set.nextSetBit(0); id >= 0; id = set.nextSetBit(id + 1)) {
  // do stuff to a set index
}

在您进行填充操作后。这相当于在
集合的元素上迭代

如果该位集合由一个long[]支持,则最小大小为64(因为1 long是64位)。大小增加了64倍,并且由于某种原因,它们没有保留您在使用接受int的构造函数时要表示的位的数量。

这也让我感到困惑,我不确定位集当前相当意外的功能背后的原理。但是,由于它不是最终的,我们可以使用一些拥抱和扩展策略并执行以下操作以获得具有预期长度语义的固定位集:

import java.util.BitSet;

/**
 * Variation of BitSet which does NOT interpret the highest bit synonymous with
 * its length.
 *
 * @author casper.bang@gmail.com
 */
public class FixedBitSet extends BitSet{

    int fixedLength;

    public FixedBitSet(int fixedLength){
        super(fixedLength);
        this.fixedLength = fixedLength;
    }

    @Override
    public int length() {
        return fixedLength;
    }
}

好样的Casper!您的小改进确实应该出现在原始的位集java def中!我还建议这样做(append()和concat()对于各种用途都很有用)

import java.util.BitSet;
公共类固定位集扩展位集{
公共int fsize=0;
公共无效集(int k,布尔值){
如果(k>=fsize)
fsize=k+1;
super.set(k,值);
}
公共void追加(固定位集bs){
对于(int k=0;k
//Abhay Dandekar

import java.util.BitSet;

public class TestBitSet {

    public static void main(String[] args) {

        BitSet bitSet = new BitSet();
        System.out.println("State 0 : " + bitSet.size() + " : " + bitSet.length() );

        bitSet.set(0, true);
        bitSet.set(1, true);
        System.out.println("State 1 : " + bitSet.size() + " : " + bitSet.length() );

        bitSet.set(2, false);
        bitSet.set(3, false);
        System.out.println("State 2 : " + bitSet.size() + " : " + bitSet.length() );

        bitSet.set(4, true);
        System.out.println("State 3 : " + bitSet.size() + " : " + bitSet.length() );

    }
}
一个简单的java程序,用于显示内部发生的情况。请注意以下几点:

  • 位集由一个长的

  • 所有默认值都为false

  • 返回长度时,它返回集合中最高“true”值的索引+1

  • 下面的输出应该能够自我解释:

    State 0 : 64 : 0
    
    State 1 : 64 : 2
    
    State 2 : 64 : 2
    
    State 3 : 64 : 5
    
    因此,可以得出以下结论:

  • 不要使用长度来推断修改的位数

  • 可用于布卢姆过滤器等场景。有关布卢姆过滤器的更多信息,请在谷歌上搜索……)

  • 希望这有帮助

    问候,


    Abhay Dandekar

    ZZ,我把它清理干净,以确保它是清晰的(并且+1'ed了),希望你不介意。考虑到我最初将“set”误解为“已经设置为任何东西”,小人物也可能有这个问题:-)“或者世界上没有人真正使用java.util.BitSet吗?”。。。是的,对了,拉另一个-上面有铃铛@斯蒂芬:还有哪一个?;-)很好的解释。基本上,位集似乎不太适合表示固定长度的位字段(或位数组)。好吧,对于固定长度,如果不依赖位集来保持长度,也没关系。如果希望位集为您处理长度,您会失望的。
    import java.util.BitSet;
    
    public class TestBitSet {
    
        public static void main(String[] args) {
    
            BitSet bitSet = new BitSet();
            System.out.println("State 0 : " + bitSet.size() + " : " + bitSet.length() );
    
            bitSet.set(0, true);
            bitSet.set(1, true);
            System.out.println("State 1 : " + bitSet.size() + " : " + bitSet.length() );
    
            bitSet.set(2, false);
            bitSet.set(3, false);
            System.out.println("State 2 : " + bitSet.size() + " : " + bitSet.length() );
    
            bitSet.set(4, true);
            System.out.println("State 3 : " + bitSet.size() + " : " + bitSet.length() );
    
        }
    }