BitSet 是个好东西
Posted LarryZeal
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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其他的操作,留给各位自行探索吧。
以上是关于BitSet 是个好东西的主要内容,如果未能解决你的问题,请参考以下文章