简体   繁体   English

java.util.BitSet — set()不能按预期工作

[英]java.util.BitSet — set() doesn't work as expected

Am I missing something painfully obvious? 我是否错过了明显痛苦的事情? Or does just nobody in the world actually use java.util.BitSet? 还是世界上没有人真正使用java.util.BitSet?

The following test fails: 以下测试失败:

@Test
public void testBitSet() throws Exception {
    BitSet b = new BitSet();
    b.set(0, true);
    b.set(1, false);
    assertEquals(2, b.length());
}

It's really unclear to me why I don't end up with a BitSet of length 2 and the value 10. I peeked at the source for java.util.BitSet, and on casual inspection it seems to fail to make sufficient distinction between a bit that's been set false and a bit that has never been set to any value... 我真的不清楚,为什么我没有得到长度为2的BitSet和值为10的结果。我偷看了java.util.BitSet的源代码,并且在随意检查时似乎无法对两者进行足够的区分。设置为false,并且从未设置为任何值...

(Note that explicitly setting the size of the BitSet in the constructor has no effect, eg: (请注意,在构造函数中显式设置BitSet的大小无效,例如:

BitSet b = new BitSet(2);

You highest bit set (as in "set to 1") is Bit 0. So the length should be 1. 您设置的最高位(如“设置为1”中的位)是位0。因此长度应为1。

See the JavaDoc for length : 有关长度,请参见JavaDoc

public int length() public int length()

Returns the "logical size" of this BitSet: the index of the highest set bit in the BitSet plus one. 返回此BitSet的“逻辑大小”:BitSet中最高设置位的索引加1。 Returns zero if the BitSet contains no set bits. 如果BitSet不包含任何设置位,则返回零。

Maybe you're looking for size although it's possible that might be higher than two if bits are allocated at a certain resolution (say 16 bit boundaries)? 也许你正在寻找的大小虽然有可能,如果位在某个分辨率(16说位边界)分配可能超过两更高

People do use BitSet ; 人们确实使用BitSet ; however, they use it for something other than what you intend. 但是,他们将其用于其他用途。 It's probably best to think of BitSet as a very compact, memory-efficient form of Set<Integer> that has the peculiar property that you can't put negative numbers into it. 最好将BitSet视为Set<Integer>一种非常紧凑的内存有效形式,它具有奇特的属性,您不能在其中添加负数。

It's very common with BitSet s to use them in the pattern of BitSet的模式使用它们在BitSet很常见

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

after you do something to fill them up. 在您做一些事以填补他们之后。 This is equivalent to iterating over the elements of the Set . 这等效于迭代Set的元素。

This puzzled me too, not sure of the rationale behind BitSet's current rather unexpected functionality. 这也让我感到困惑,不确定BitSet当前相当意外的功能背后的原理。 However since it's not final, we can use some embrace and extend tactics and do the following to get a fixed BitSet with length semantics as expected: 但是,由于它不是最终的,我们可以使用一些拥抱和扩展策略,并按照预期进行以下操作以获得具有长度语义的固定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;
    }
}

Given that the bitset is backed by a long[], the minimum size is 64 (because 1 long is 64 bits). 假设该位集由long []支持,则最小大小为64(因为1 long为64位)。 The size gets incremented by a multiple of 64 and for some reason, they have not maintained the # of bits you intended to represent when you use the constructor that takes an int. 大小增加了64的倍数,并且由于某种原因,它们没有维护使用带int的构造函数时要表示的位数。

// Abhay Dandekar // 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() );

    }
}

A simple java program to show what happens inside. 一个简单的Java程序来显示内部发生的事情。 Some points to note : 注意事项:

  1. BitSet is backed by a long BitSet由长期支持

  2. All the default values are false 所有默认值均为false

  3. While returning the length, it returns the index+1 of the highest "true" value in the set. 返回长度时,它返回集合中最高“ true”值的索引+1。

The output below should be able to explain itself : 下面的输出应该能够解释自己:

State 0 : 64 : 0

State 1 : 64 : 2

State 2 : 64 : 2

State 3 : 64 : 5

So points to conclude : 因此,得出以下结论:

  1. Do not use the length to conclude the no of bits modified 不要使用长度来推断修改的位数

  2. Can be used in scenarios like bloom filters. 可以在布隆过滤器之类的场景中使用。 More on bloom filters can be googled .. ;) 更多关于bloom过滤器的信息可以在谷歌上搜索..;)

Hope this helps 希望这可以帮助

Regards, 问候,

Abhay Dandekar 阿比·丹德卡(Abhay Dandekar)

Good Casper! 好卡斯珀! Your small improvement should indeed have been present in the original BitSet java def! 您的小改进确实应该已经存在于原始BitSet java def中! I also suggest this (append() and concat() are useful for various usages) 我也建议这样做(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);
  }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM