BitSet 是个好东西

顾名思义,就是位集合(bit set),是从JDK 1.0就出现的东西,后面的版本又慢慢强化。

我们说学习一样东西,最好是场景驱动 - 要考虑它的使用场景,这样才有意义。

那么,BitSet的应用场景是什么?

我个人的体会是,用于统计,统计整数相关的东西。但这么说未免太空泛了,我们先来看一下它的用法吧。

直接上例子:

@Test
public void test(){
    BitSet set = new BitSet(10); //10 bits set

    //set() 设为true
    set.set(0);
    set.set(1);
    set.set(5);
    System.out.println(set); // 应该是列出值为true的那些位的坐标!

    // 8 bit >> 1 byte,  就是说截取8位,转成byte。 就是0010 0011 >>
    System.out.println(Arrays.toString(set.toByteArray()));
    // 64 bit >> 1 long
    System.out.println(Arrays.toString(set.toLongArray()));
}
 

方法体内:

第一部分是创建对象,该构造方法接收一个int来指明位集合的长度 -- [0,0,0,0,  0,0,0,0,  0,0]。注意,此时所有位的值都是false - 这里的false不是Java中的概念,而是对应bit的0 -- true对应1。

第二部分是设置位值,BitSet#set(int n) 方法是将第n位的值设为true(1) --  [1,1,0,0,  0,1,0,0,  0,0]!直接输出的话,就是位值为true的索引:{0, 1, 5}!

第三部分,是将所有位转成byte数组、long数组,并输出对应的数组内容。转成byte[],其实就是每8位切分一下;转成long[]就是每64位切分一下!那么[1,1,0,0,  0,1,0,0,  0,0]就是[(1,1,0,0,  0,1,0,0,)  0,0],也就是[35]!注意计算方式。

再来一个逆向的例子:

@Test
public void test1(){
    // 和test()中的set.toByteArray()刚好相反,这里是1 byte >> 8 bits! 需要确认90对应的低8bit 还是高8bit。
    BitSet bitSet = BitSet.valueOf(new byte[]{90, 92, 95, 97});
    System.out.println(bitSet); //{1, 3, 4, 6, 10, 11, 12, 14, 16, 17, 18, 19, 20, 22, 24, 29, 30}

    //截取下上面的输出即可知道90对应的是低位还是高位
    BitSet bs = new BitSet(8);//
    bs.set(1);
    bs.set(3);
    bs.set(4);
    bs.set(6);
    System.out.println(Arrays.toString(bs.toByteArray()));//90 - 事实证明是小端?
}

这里就是将byte[]或long[]中的每个值拆成8bit或者64bit的形式,填入相应的位置(8*index ~ 8*(index+1),或64*index ~ 64*(index+1))。

然后,具体的计算就跟2进制转8进制或16进制一样,每三位一算,或每四位一算!只不过这里是每8位或每64位一算!

那回到前面的主题,这有什么应用场景?

举个例子,比如你要生成随机数,整数,不多,就 0~1亿范围吧,生成的数量不定,现在让你列出所有生成的数值,甚至按照大小排序,你怎么做?

难道是搞一个HashSet<Integer>?哪怕是按照int类型的长度,最大也会4B*100000000 ≈ 381 MB,性能绝对是个问题,还得排序,估计得到地老天荒。

用BitSet就方便多了,怎么用呢?

直接搞一个 new BitSet(100000000),内存不过是 100000000/8 B ≈ 12 MB!

然后,每得到一个随机数,就将相应的位设为true即可,bs.set(num)!

最后,直接输出所有位值为true的索引即可,无论从小到大,还是反过来,都很简单!

怎么样,有没有一种惊喜的感觉,哈哈,起码我觉得很惊喜。

噢对了,这货C++中也有。

至于BitSet其他的操作,留给各位自行探索吧。

原文地址:https://www.cnblogs.com/larryzeal/p/7710389.html