1.BitSet介绍
BitSet是用于存储二进制位和对二进制进行操作的Java数据结构,BitSet从jdk1.0开始就有了。它存储的是二进制位在BitSet中状态,根据对这些状态的判断,可以有很多应用。以前对数据的操作都是先把数据都是存储在内存中间的,现在可以通过设置BitSet的相应位达到存储数据信息的目的,极大的节省了内存空间。
2.BitSet应用
BitSet可以做的事情主要分为以下几类:
(1)大数据量的查找。
(2)大数据量的去重。
(3)大数据量的统计。
(4)大数据量的排序。
(5)求数据的并集、交集、补集等。
(6)大数据量的判别。
BitSet常见的应用是那些对海量数据进行一些统计工作,比如日志分析、用户数统计等等。
BitSet能够做以上事情主要依靠BitSet的基本操作,对应的常用方法:
(1)初始化一个BitSet。使用构造函数BitSet( )或BitSet(int nbits)。
(2)设置BitSet的某一指定位。就是把指定位存放入BitSet,使用设置函数set(int bitIndex)。
(3)获取BitSet的某一位的状态。就是判断指定位是否在BitSet中,boolean型的返回值,使用函数get(int bitIndex)。
(4)清空BitSet或清空BitSet的某一指定位。就是把BitSet所有位或指定位清除,使用清空函数clear( )或clear(int bitIndex)。
不过使用BitSet有一点需要注意:在没有外部同步的情况下,多个线程操作一个BitSet是不安全的。所以在多线程环境下使用BitSet要考虑线程安全的问题,可以使用多线程安全策略确保多个线程在执行过程中的的线程安全性。也就是BitSet是非线程安全的,需要外部同步。
2.BitSet应用举例
下面就来看一个BitSet应用的具体例子。
(1)使用BitSet查找电话号码
从一堆数量大概在千万级的电话号码列表中找出所有重复的电话号码,需要时间复杂度尽可能小。
如果这个问题使用暴力搜索时间复杂度太高,就不考虑这种解决方案。
容易想到的办法就是建立一个标志数组,int boolean都行,用相应的位置值来代替这个号码是否出现,根据数组的可直接存取特性,来提高效率。比如电话号“8832061”如果存在,就把他放入数组的第8832061位设置该位的值为1或true。
但是这样做有一个缺点就是int型的字段太过于占空间,我们只需要知道这个号码存在与否,所以最简单的0和1就够用了,能表示0和1的最小存储单位是什么呢?是内存中的一位。BitSet是用于存储二进制位和对二进制进行操作的数据结构。
之前int型的一个电话号码的状态要占4个字节,现在使用BitSet存储出现的电话号码的位置,而且BitSet有自动去重功能。8bit是1byte,int占用4byte,那么使用的空间大小就缩小了4*8 = 32倍。使用了内存大大减少。
下面的简单代码给出了BitSet的例子:
import java.util.BitSet;
public class BitSetDemo {
public static void main(String[] args) {
//创建一个具有10000000位的bitset 初始所有位的值为false
BitSet bitSet = new BitSet(10000000);
//将指定位的值设为true
bitSet.set(9999);
//或者bitSet.set(9999,true);
//输出指定位的值
System.out.println("9999:"+bitSet.get(9999));
System.out.println("9998:"+bitSet.get(9998));
}
}
程序运行结果:第一行输入“true”,第二个输出“false”。