Java BitSet 示例

63
我正在寻找一个好的Java BitSet示例,以便处理0和1。我尝试查看Javadocs,但仅仅通过阅读那些内容,我不理解这个类的用法。例如,如何在两个不同的BitSet对象上使用and、or和xor方法?
例如:
  BitSet bits1 = new BitSet();
  BitSet bits2 = new BitSet();

  bits2.set(1000001);
  bits1.set(1111111);

  bits2.and(bits1);

  System.out.println(bits2);

如果我这样做,它会返回空的bits2,为什么会这样?


2
它们的工作方式与使用原始数字类型进行& | ^等操作完全相同。 - Brian Roach
你具体不理解什么?你创建一个BitSet,然后调用它的函数,例如.and.or.xor。每个函数都以另一个BitSet对象作为参数。 - Tony
好的,我尝试在上面的示例中执行“and”操作,但位集变为空。 - Steffan Harris
7个回答

113

针对您提到的具体问题:当您调用bits2.set(1000001)时,您将第一百万个位设为true。然后,当您与设置了第一百万、第一千一百一十一万零一百一十一个位的bits1相交时,它们没有任何公共位。

我想您原本的意图是

 bits2.set(0); // set the 0th bit
 bits2.set(6); // set the 6th bit

这有助于澄清问题吗?


"它们没有任何共同的位",你是怎么说的?因为我看到bits1和bits2的第一个和最后一个位是相同的,对吧?但我还是不明白为什么bits2变成了空的。你能否再详细解释一下? - JAVA
6
@JAVA,我不知道该如何更清楚地解释了。 bits1 只有一个位被设置为 true,即第一百万零一(1,000,001)位上的位,而 bits2 只有一个位被设置为 true,即第一千一百一十一万一千一百一十一(1,111,111)位上的位。我会尽力使翻译更加通俗易懂,但不会改变原句的含义。 - Louis Wasserman

60

如果你想在Java 7中使用位(bit)操作,你可以使用int类型的值。

int bits2 = 0b1000001;
int bits1 = 0b1111111;
bits2 &= bits1;
System.out.println(Integer.toBinaryString(bits2));

打印

1000001

1
当你将它们保存为 ints 时,它们占用的是 4字节 还是 7位 - daydreamer
2
@daydreamer 查看源代码可以发现,BitSet在后台是由long[]实现的。 "第i位存储在bits[i/64]中,位于i%64的位置(其中位0指最低有效位,63指最高有效位)"。因此,任何BitSet至少将使用64位。即使是参数化构造函数也说“创建一个初始大小足够大的位集,以显式表示范围内索引的位...” - mbomb007

49

BitSet没有方便的方法来接受这样的位字符串。我提供了一些方法,现在例子可以按照您的期望工作。请注意,这使用了Java 7中的新功能;如果您想使用Java 6,可以很容易地在网上找到这些方法的实现。

import java.util.BitSet;

class Scratch {
    public static void main(String[] args) {
        BitSet bits1 = fromString("1000001");
        BitSet bits2 = fromString("1111111");

        System.out.println(toString(bits1)); // prints 1000001
        System.out.println(toString(bits2)); // prints 1111111

        bits2.and(bits1);

        System.out.println(toString(bits2)); // prints 1000001
    }

    private static BitSet fromString(final String s) {
        return BitSet.valueOf(new long[] { Long.parseLong(s, 2) });
    }

    private static String toString(BitSet bs) {
        return Long.toString(bs.toLongArray()[0], 2);
    }
}

1
太完美了!我喜欢你的 toString(BitSet bs) 方法。非常有用!你可以翻转位以将 bit_0 放在右侧。 - Magno C
这是最佳答案,因为它理解了OP的困惑(以及我的),并直接切入主题。 - kellyfj

8
以下是一些有关 bitSet 的链接,可以帮助您: 更新: 文档中指出:

public void set(int bitIndex)

Sets the bit at the specified index to true.
当您调用bits2.set(10);时,它被视为十进制的10而不是1 0,因此您得到的数字是1000000000
在这个例子中,要正确设置第二位为1,所以我调用bits2.set(1);,因为索引从0开始。 总之,对于每个设置为1的位,您需要调用bitSet.Set并提供它的位索引。

6
我将分享我的实现方式,使用位字符串作为输入创建一个BitSet对象。
private static BitSet createFromString(String s) {
    BitSet t = new BitSet(s.length());
    int lastBitIndex = s.length() - 1;

    for (int i = lastBitIndex; i >= 0; i--) {
        if ( s.charAt(i) == '1'){
            t.set(lastBitIndex - i);                            
        }               
    }

    return t;
}

对于字符串输入 "1001"

BitSet s1 = createFromString("1001");
    System.out.println(s1);

输出:

{0, 3}

1
你为什么要使用while循环?使用for循环同样可以,因为你每次迭代都会将i减1。 - Clément
编辑:使用For循环的更好版本的代码,感谢@Clément的建议 :) - Aditya Gaykar

0

试试这个:

import java.util.BitSet;

public class BitSetExample {

    public static void main(String args[]){
        BitSet bits1 = new BitSet(7);
        BitSet bits2 = new BitSet(7);

        // set some bits
        for(int i = 0; i < 7; i++) {
            if((i % 2) == 0) bits1.set(i);
            if((i % 3) != 0) bits2.set(i);
        }

        System.out.println("BitSet1: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits1.get(i)? "1 ": "0 ");
        }

        System.out.println("\nBitSet2: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits2.get(i)? "1 ": "0 ");
        }

        System.out.println();

        //And
        bits1.and(bits2);

        System.out.println("b1 = b1 AND b2\nBitSet1: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits1.get(i)? "1 ": "0 ");
        }

        System.out.println();
        System.out.println("BitSet2: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits2.get(i)? "1 ": "0 ");
        }

        System.out.println();

        //Or
        bits1.or(bits2);

        System.out.println("b1 = b1 OR b2\nBitSet1: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits1.get(i)? "1 ": "0 ");
        }

        System.out.println();
        System.out.println("BitSet2: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits2.get(i)? "1 ": "0 ");
        }

        System.out.println();

        //Xor
        bits1.xor(bits2);

        System.out.println("b1 = b1 XOR b2\nBitSet1: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits1.get(i)? "1 ": "0 ");
        }

        System.out.println();
        System.out.println("BitSet2: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits2.get(i)? "1 ": "0 ");
        }

        System.out.println();

        //Setting bits to zero and one
        bits1.set(1);
        bits2.set(1,false);

        System.out.println("set bit 1 of BitSet1 to one and set bit 1 of BitSet2 to zero\nBitSet1: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits1.get(i)? "1 ": "0 ");
        }

        System.out.println();
        System.out.println("BitSet2: ");

        for(int i = 0; i < 7; i++) {
            System.out.print(bits2.get(i)? "1 ": "0 ");
        }

        System.out.println();

    }
}

希望这对你有用。欲了解更多信息,请访问:https://github.com/m-vahidalizadeh/foundations/blob/master/src/data_structures/BitSetExample.java


0

如果您需要处理比Integer.MAX_VALUE更长的位地址,我修改了java.util.BitSet这里:LongBitSet)以接受get和set方法中的长整型输入。我这样做是为了充分利用内存进行素数筛选实验。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接