Java7 BitSet 类增强

BitSet 类在 Java 1.0 版本就已经被引入了。它是 Java 核心类库中的一部分,并且在后续的 Java 版本中一直存在并得到支持和优化。

BitSet 是一个表示 bit(二进制位)序列的整数集合。该集合可以根据整数 i 来设置第 i 个 bit 位的值。这使得集合操作非常高效。求并集、交集、补集只不过是简单的按位或、与、非运算。

默认情况下,集合中的所有位初始值都是 false。

每个位集都有一个当前大小,即位集当前使用的空间位数。请注意,大小与位集合的实现有关,因此可能会随着实现而改变。位集合的长度与位集合的逻辑长度有关,其定义与实现无关。

除非另有说明,否则向 BitSet 中的任何方法传递空参数都会导致 NullPointerException 异常。

在没有外部同步的情况下,BitSet 对于多线程使用是不安全的。

BitSet 构造方法

  • BitSet() 创建一个新的位集。

  • BitSet(int nbits) 创建一个比特集合,其初始大小足以明确表示索引范围在 0 到 nbits-1 之间的比特。

示例:

BitSet bitSet = new BitSet();
System.out.println(bitSet.isEmpty()); // true

BitSet bitSet2 = new BitSet(8);
System.out.println(bitSet2.size()); // 64

为什么 size() 返回的不是 8,而是 64 呢?调试一下:

8536dc76e8dc0c576c977250949f4bc3_1722920970113-283c9914-59b0-4db5-9468-859834e050b3_x-oss-process=image%2Fformat%2Cwebp.png

其中,words 是一个 long 数组,如下图:

8e04b95e3d00f2f13ee6db352dc2415e_1722921006363-bfda2c8e-d22b-4cb7-a79c-d3cc24b8c2f7_x-oss-process=image%2Fformat%2Cwebp.png

而 BITS_PER_WORD 是一个常量,如下图:

50035f2689f7f961cf485f7bfc494d5a_1722922329408-30da38b5-d1e2-43ab-a756-014c53f85c86_x-oss-process=image%2Fformat%2Cwebp.png

BITS_PER_WORD 的值是将 1 左移 6 位,0000 0001 左移 6 位为 0100 0000,即为 64。

BitSet Java7 增强

Java7 添加了一些构造 BitSet 的方法,例如:

package com.hxstrive.jdk7.bitset;

import java.util.BitSet;

/**
 * BitSet 类
 * @author hxstrive.com
 */
public class BitSetDemo2 {

    private static String show(BitSet bits) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < bits.size(); ++i) {
            result.append(bits.get(i) ? "1" : "0");
        }
        return result.toString();
    }

    public static void main(String[] args) {
        // 使用 long 初始化
        // 6 的二进制为 0b0110,因此下标为 1 和 2 的位为 true
        BitSet base = BitSet.valueOf(new long[]{ 6L });
        System.out.println(show(base));
        System.out.println(base);
        // 0110000000000000000000000000000000000000000000000000000000000000
        // {1, 2}
        // 注意:BitSet 的 toString() 方法将返回位为 true 的下标值

        // 使用 byte 初始化
        // 1010 1100 0010 1000
        byte[] bytes = { (byte)0b10101100, (byte)0b00101000 };
        BitSet primes = BitSet.valueOf(bytes);
        System.out.println(show(primes));
        System.out.println(primes);
        // 0011010100010100000000000000000000000000000000000000000000000000
        // 00110101 00010100 BitSet中的字节顺序
        // 10101100 00101000 真实的字节顺序
        // {2, 3, 5, 7, 11, 13}
    }

}

根据上面示例可知,在 BitSet 中,存放字节的顺序和实际表示的字节顺序相反,例如:

(1)假如存在如下两个字节:

    10101100

    00101000

(2)在 BitSet 中存放如下:

    a、先存放 10101100,将地位存放在高位,高位存放在地位,存放结果为:00110101

    b、再次存放 00101000,存放结果为:00010100

(3)最后 BitSet 中的内容为:

    00110101 00010100

如果要获得对应的引用类型,则调用方法为 toByteArray 和 toLongArray。

package com.hxstrive.jdk7.bitset;

import java.util.Arrays;
import java.util.BitSet;

/**
 * BitSet 类
 * @author hxstrive.com
 */
public class BitSetDemo3 {

    public static void main(String[] args) {
        // 使用 long 初始化
        BitSet base = BitSet.valueOf(new long[]{ 6L });
        System.out.println(Arrays.toString(base.toLongArray()));
        //[6]

        // 使用 byte 初始化
        byte[] bytes = { (byte)0b10101100, (byte)0b00101000 };
        BitSet primes = BitSet.valueOf(bytes);
        System.out.println(Arrays.toString(primes.toByteArray()));
        //[-84, 40]
    }

}

注意:在 Java8 中,BitSet 提供了一个可以返回 IntStream 的 stream 方法。例如:

package com.hxstrive.jdk8.bitset;

import java.util.BitSet;
import java.util.stream.IntStream;

/**
 * BitSet 类
 * @author hxstrive.com
 */
public class BitSetDemo1 {

    public static void main(String[] args) {
        BitSet base = BitSet.valueOf(new long[]{ 0b0110_0101L });
        IntStream stream = base.stream();
        stream.forEach(System.out::print);
        //结果:
        //0256
    }

}

BitSet 常用方法

以下是 BitSet 类的一些常用方法:

  • void set(int bitIndex):将指定索引位置的位设置为 true,即位的值为 1。

  • void clear(int bitIndex):将指定索引位置的位设置为 false,即位的值为 0。

  • void clear():将 BitSet 中的所有位设置为 false。

  • boolean get(int bitIndex):获取指定索引位置的位的值。

  • int cardinality():返回 BitSet 中设置为 true 的位的数量。

  • int nextSetBit(int fromIndex):返回指定索引位置(fromIndex)之后第一个设置为 true 的位的索引。如果没有这样的位,则返回 -1。

  • int previousSetBit(int fromIndex):返回指定索引位置(fromIndex)之前第一个设置为 true 的位的索引。如果没有这样的位,则返回 -1。

  • void and(BitSet set):执行当前 BitSet 与给定 BitSet 的逻辑与操作。

  • void or(BitSet set):执行当前 BitSet 与给定 BitSet 的逻辑或操作。

  • void xor(BitSet set):执行当前 BitSet 与给定 BitSet 的逻辑异或操作。

示例:

package com.hxstrive.jdk7.bitset;

import java.util.BitSet;

/**
 * BitSet 类
 * @author hxstrive.com
 */
public class BitSetDemo4 {

    public static void main(String[] args) {
        BitSet bitSet1 = new BitSet();
        BitSet bitSet2 = new BitSet();

        bitSet1.set(0); // 将下标为0的位设置为1,即true
        bitSet1.set(2);
        bitSet1.set(4);

        bitSet2.set(1);
        bitSet2.set(2);
        bitSet2.set(3);

        System.out.println("BitSet1: " + bitSet1); //BitSet1: {0, 2, 4}
        System.out.println("BitSet2: " + bitSet2); //BitSet2: {1, 2, 3}

        // 执行逻辑与操作
        //BitSet1: {0, 2, 4}
        //BitSet2: {1, 2, 3}
        bitSet1.and(bitSet2);
        System.out.println("After AND operation: " + bitSet1); //After AND operation: {2}

        // 重新设置 bitSet1
        bitSet1.set(0);
        bitSet1.set(2);
        bitSet1.set(4);
        System.out.println("bitSet1:" + bitSet1); //bitSet1:{0, 2, 4}

        // 执行逻辑或操作
        //BitSet1: {0, 2, 4}
        //BitSet2: {1, 2, 3}
        bitSet1.or(bitSet2);
        System.out.println("After OR operation: " + bitSet1); //After OR operation: {0, 1, 2, 3, 4}

        // 重新设置 bitSet1
        bitSet1.set(0);
        bitSet1.set(2);
        bitSet1.set(4);
        System.out.println("bitSet1:" + bitSet1); //bitSet1:{0, 2, 4}

        // 执行逻辑异或操作
        //BitSet1: {0, 2, 4}
        //BitSet2: {1, 2, 3}
        show(bitSet1);
        //1111100000000000000000000000000000000000000000000000000000000000
        show(bitSet2);
        //0111000000000000000000000000000000000000000000000000000000000000
        bitSet1.xor(bitSet2);
        System.out.println("After XOR operation: " + bitSet1); //After XOR operation: {0, 4}
    }

    private static void show(BitSet bitSet) {
        for(int i = 0; i < bitSet.size(); i++) {
            System.out.print(bitSet.get(i) ? "1" : "0");
        }
        System.out.println();
    }

}


说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号