java.util.BitSet - set()无法按预期工作

时间:2010-05-18 01:40:13

标签: 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的BitSet。我偷看了java.util.BitSet的源代码,并且在随意检查时似乎没有做出足够的区分在设置为false的位和从未设置为任何值的位之间...

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

BitSet b = new BitSet(2);

6 个答案:

答案 0 :(得分:8)

您的最高位设置(如“设置为1”)是位0.因此长度应为1.

请参阅JavaDoc for length

  

public int length()

     

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

也许你正在寻找size,如果在某个分辨率(例如16位边界)分配比特,那么可能高于

答案 1 :(得分:6)

人们确实使用BitSet;但是,他们将它用于你想要的东西以外的东西。最好将BitSet视为一种非常紧凑,记忆效率高的Set<Integer>形式,具有独特的属性,你不能将负数放入其中。

BitSet s以

的模式使用它们非常常见
for (int id = set.nextSetBit(0); id >= 0; id = set.nextSetBit(id + 1)) {
  // do stuff to a set index
}

在你做一些事情来填补它们之后。这相当于迭代Set

的元素

答案 2 :(得分:3)

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

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;
    }
}

答案 3 :(得分:2)

鉴于bitset由long []支持,最小大小为64(因为1 long是64位)。大小增加了64的倍数,并且出于某种原因,当你使用带有int的构造函数时,它们没有保持你想要表示的位数。

答案 4 :(得分:1)

// 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程序,用于显示内部发生的情况。有些要点需要注意:

  1. BitSet由长

  2. 支持
  3. 所有默认值均为false

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

  5. 下面的输出应该能够解释自己:

    State 0 : 64 : 0
    
    State 1 : 64 : 2
    
    State 2 : 64 : 2
    
    State 3 : 64 : 5
    

    所以要点得出结论:

    1. 不要使用长度来结束修改后的位数

    2. 可以在bloom过滤器等场景中使用。有关布隆过滤器的更多内容可以用Google搜索..;)

    3. 希望这有帮助

      此致

      Abhay Dandekar

答案 5 :(得分:0)

好卡斯帕尔!您的小改进应该确实存在于原始的BitSet java def中!我也建议这个(append()和concat()对各种用法都很有用)

import java.util.BitSet;

public class fixBitSet extends BitSet {

  public int fsize = 0;

  public void set(int k, boolean value) {
    if (k >= fsize)
      fsize = k + 1;
    super.set(k, value);
  }

  public void append(fixBitSet bs) {
    for (int k = 0; k < bs.fsize; k++)
      super.set(fsize + k, bs.get(k));
    fsize += bs.fsize;
  }

  public static fixBitSet concat(fixBitSet[] vbs) {
    final fixBitSet bs = new fixBitSet();
    for (fixBitSet xbs : vbs)
      bs.append(xbs);
    return (bs);
  }

}