BitSet的作用
- 使用BitSet可以节省存储空间
- 可以在o(1)的复杂度查询出某个值是否存在
Set方法
public void set(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
expandTo(wordIndex);
words[wordIndex] |= (1L << bitIndex); // Restores invariants
checkInvariants();
}
BitSet使用一个long类型的数组。即set方法中的words数组。
private static int wordIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;
}
wordIndex方法用于计算输入值在long数组中的位置,其中ADDRESS_BITS_PER_WORD=6,由于long类型的值占64位,64=2^6,因此,bitIndex>>ADDRESS_BITS_PER_WORD=>bitIndex/64。由于每个long类型的元素只能够标记64个数字,因此,wordIndex这个函数用于确定新添加的数应该由哪个long类型 的数来标记。
//该方法主要用于扩容
private void expandTo(int wordIndex) {
int wordsRequired = wordIndex+1;
if (wordsInUse < wordsRequired) {
ensureCapacity(wordsRequired);
wordsInUse = wordsRequired;
}
}
最重要的一条语句是:
words[wordIndex] |= (1L << bitIndex);
long类型的数执行<<操作,当左移位数是64或者64的倍数时,执行左移操作后与执行左移操作前的值相等。正是由于这一特性可以使这条语句达到为加入的数在指定位置设置标志的作用。指定位置等于1表示该值存在,指定位置等于0表示该值不存在。
get方法
public boolean get(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
checkInvariants();
int wordIndex = wordIndex(bitIndex);
return (wordIndex < wordsInUse)
&& ((words[wordIndex] & (1L << bitIndex)) != 0);
}
get方法用于返回指定值是否存在。使用wordIndex计算目标值在words数组中的下标,如果下标未超出边界 且 对应位置的标志为1 表示目标值存在,否则目标值不存在。
使用BitSet这种思想可以减少空间的使用,同时快速确定元素是否存在。