该类在java的java.util包中。
BitSet类的原理主要是利用long型有64个bit,每个bit存储一个数值,这样一个long型数字就能存储64个数字,进而节省了空间。接下来我们开始讲解该类的代码。
我们先看一下该类的成员变量:
/*
* BitSets are packed into arrays of "words." Currently a word is
* a long, which consists of 64 bits, requiring 6 address bits.
* The choice of word size is determined purely by performance concerns.
*/
private final static int ADDRESS_BITS_PER_WORD = 6;
private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
private final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;
/* Used to shift left or right for a partial word mask */
private static final long WORD_MASK = 0xffffffffffffffffL;
/**
* @serialField bits long[]
*
* The bits in this BitSet. The ith bit is stored in bits[i/64] at
* bit position i % 64 (where bit position 0 refers to the least
* significant bit and 63 refers to the most significant bit).
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("bits", long[].class),
};
/**
* The internal field corresponding to the serialField "bits".
* //存储数据,一个元素可以存储64个数据
*/
private long[] words;
/**
* The number of words in the logical size of this BitSet.
* 当前已经在使用了的数组元素个数
*/
private transient int wordsInUse = 0;
/**
* Whether the size of "words" is user-specified. If so, we assume
* the user knows what he's doing and try harder to preserve it.
* 是否指定words数组的大小,如果是那么就为true,否则为false。
*/
private transient boolean sizeIsSticky = false;
/* use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = 7997698588986878753L;
接下来我们开始分析函数:
1、wordIndex函数,代码如下:
/**
* Given a bit index, return word index containing it.
*/
private static int wordIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;
}
这个函数用来获取某个数在words数组中的索引,这里通过bitIndex右移ADDRESS_BITS_PER_WORD位,即右移6位,为什么是6位呢?
我们知道在正常情况下,右移n位得到的值为原值除以2的n次方,而2的6次方是64,也就是bitIndex/64,我们之前说过,words数组中每个元素能够代表64个数字,所以存储的值除以64来得到数组索引值,例如0到63的索引值为0,那么这64个数字划归到第一个数组元素中,64到127划归到第二个数组元素中,以此类推。
2、checkInvariants()函数,代码如下:
/**
* Every public method must preserve these invariants.
*/
private void checkInvariants() {
assert(wordsInUse == 0 || words[wordsInUse - 1] != 0);
assert(wordsInUse >= 0 && wordsInUse <= words.length);
assert(wordsInUse == words.length || words[wordsInUse] == 0);
}
这个函数用来验证当前对象的有效性,比较简单。
3、recalculateWordsInUse()函数,代码如下:
/**
* Sets the field wordsInUse to the logical size in words of the bit set.
* WARNING:This method assumes that the number of words actually in use is
* less than or equal to the current value of wordsInUse!
*/
private void recalculateWordsInUse() {
// Traverse the bitset until a used word is found
int i;
for (i = wordsInUse-1; i >= 0; i--)
if (words[i] != 0)
break;
wordsInUse = i+1; // The new logical size
}
这个函数用来计算当前已经使用了的最大数组元素个数。
4、initWords函数,代码如下:
private void initWords(int nbits) {
words = new long[wordIndex(nbits-1) + 1];
}
这个函数用来创建数组words,该数组元素大小通过wordIndex(nbits-1)+1来获取,而wordIndex上面我们讲了,用来得到某个值所在words数组的索引,然后创建words数组的时候一定要保证数组个数大于等于该值所在的索引值。
5、构造函数
/**
* Creates a new bit set. All bits are initially {@code false}.
*/
public BitSet() {
//创建一个words数组,大小为1
initWords(BITS_PER_WORD);
//该数组大小不限定
sizeIsSticky = false;
}
/**
* Creates a bit set whose initial size is large enough to explicitly
* represent bits with indices in the range {@code 0} through
* {@code nbits-1}. All bits are initially {@code false}.
*
* @param nbits the initial size of the bit set
* @throws NegativeArraySizeException if the specified initial size
* is negative
*/
public BitSet(int nbits) {
// nbits can't be negative; size 0 is OK
if (nbits < 0)
throw new NegativeArraySizeException("nbits < 0: " + nbits);
initWords(nbits);
//该数组大小限定
sizeIsSticky = true;
}
/**
* Creates a bit set using words as the internal representation.
* The last word (if there is one) must be non-zero.
*/
private BitSet(long[] words) {
//将该数组赋值给BitSet对象中的words数组
this.words = words;
//将当前数组正在使用的最大数组索引设置为数组元素大小
this.wordsInUse = words.length;
//验证当前对象的合法性
checkInvariants();
}
6、valueof函数,代码如下:
/**
* Returns a new bit set containing all the bits in the given long array.
*
* <p>More precisely,
* <br>{@code BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}
* <br>for all {@code n < 64 * longs.length}.
*
* <p>This method is equivalent to
* {@code BitSet.valueOf(LongBuffer.wrap(longs))}.
*
* @param longs a long array containing a little-endian representation
* of a sequence of bits to be used as the initial bits of the
* new bit set
* @return a {@code BitSet} containing all the bits in the long array
* @since 1.7
*/
public static BitSet valueOf(long[] longs) {
int n;
//倒序从longs数组中获取第一个不为0的元素所在的索引值
for (n = longs.length; n > 0 && longs[n - 1] == 0; n--)
;
//从longs数组中拷贝索引从0到n的元素,放到新创建的数组中,然后将该新数组构造BitSet类对象
return new BitSet(Arrays.copyOf(longs, n));
}
/**
* Returns a new bit set containing all the bits in the given long
* buffer between its position and limit.
*
* <p>More precisely,
* <br>{@code BitSet.valueOf(lb).get(n) == ((lb.get(lb.position()+n/64) & (1L<<(n%64))) != 0)}
* <br>for all {@code n < 64 * lb.remaining()}.
*
* <p>The long buffer is not modified by this method, and no
* reference to the buffer is retained by the bit set.
*
* @param lb a long buffer containing a little-endian representation
* of a sequence of bits between its position and limit, to be
* used as the initial bits of the new bit set
* @return a {@code BitSet} containing all the bits in the buffer in the
* specified range
* @since 1.7
*/
//其实就是将LongBuffer类对象中从position到limit中的数(倒序遍历,找到第一个不为0的数,将该数的位置当做limit)拷贝到long数组中,同时创建BitSet类对象
public static BitSet valueOf(LongBuffer lb) {
//创建一个新的LongBuffer类对象,该对象的容量是原始缓冲区的剩余元素数量(limit -
position),position为0,新对象中的值从原缓冲区中拷贝而来(从position到limit之间的值)
lb = lb.slice();
int n;
//倒序遍历新的LongBuffer类对象,直到遇到第一个不为0的值,remaining函数用来获取LongBuffer中从position到limit之间的值个数
for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--)
;
//创建数组
long[] words = new long[n];
//获取lb中从0开始到n的数据,同时拷贝到words数组中
lb.get(words);
//创建BitSet类对象
return new BitSet(words);
}
/**
* Returns a new bit set containing all the bits in the given byte array.
*
* <p>More precisely,
* <br>{@code BitSet.valueOf(bytes).get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}
* <br>for all {@code n < 8 * bytes.length}.
*
* <p>This method is equivalent to
* {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}.
*
* @param bytes a byte array containing a little-endian
* representation of a sequence of bits to be used as the
* initial bits of the new bit set
* @return a {@code BitSet} containing all the bits in the byte array
* @since 1.7
*/
public static BitSet valueOf(byte[] bytes) {
//将bytes数组中的数拷贝到BitSet类对象中
return BitSet.valueOf(ByteBuffer.wrap(bytes));
}
/**
* Returns a new bit set containing all the bits in the given byte
* buffer between its position and limit.
*
* <p>More precisely,
* <br>{@code BitSet.valueOf(bb).get(n) == ((bb.get(bb.position()+n/8) & (1<<(n%8))) != 0)}
* <br>for all {@code n < 8 * bb.remaining()}.
*
* <p>The byte buffer is not modified by this method, and no
* reference to the buffer is retained by the bit set.
*
* @param bb a byte buffer containing a little-endian representation
* of a sequence of bits between its position and limit, to be
* used as the initial bits of the new bit set
* @return a {@code BitSet} containing all the bits in the buffer in the
* specified range
* @since 1.7
*/
public static BitSet valueOf(ByteBuffer bb) {
bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
int n;
for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--)
;
long[] words = new long[(n + 7) / 8];
bb.limit(n);
int i = 0;
while (bb.remaining() >= 8)
words[i++] = bb.getLong();
for (int remaining = bb.remaining(), j = 0; j < remaining; j++)
words[i] |= (bb.get() & 0xffL) << (8 * j);
return new BitSet(words);
}
7、toByteArray()函数,代码如下:
/**
* Returns a new byte array containing all the bits in this bit set.
*
* <p>More precisely, if
* <br>{@code byte[] bytes = s.toByteArray();}
* <br>then {@code bytes.length == (s.length()+7)/8} and
* <br>{@code s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}
* <br>for all {@code n < 8 * bytes.length}.
*
* @return a byte array containing a little-endian representation
* of all the bits in this bit set
* @since 1.7
*/
public byte[] toByteArray() {
//获取当前有效的数组大小
int n = wordsInUse;
if (n == 0)
return new byte[0];
//一个数组元素有8个字节,所以总字节数为8*(n-1)+最后一个元素的有效字节数
int len = 8 * (n-1);
/*
(1)、>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后
高位,同样补0。
(2)、这是一个循环,对最后一个元素的每一个8位进行判断(从低位到高位),第一次循环,如果该元素
不为0,那么len++,然后右移8位,此时原来的元素只保留了3个字节(另外一个字节被移除掉了,
在最左边的1个字节用00000000表示,如果不为0,那么len++,继续右移8位,依次下去,直到遇到
值为0为止)
(3)、总结:
关于移位,总的原则就是:
如果左边第一个字节有值那么len+4;
如果左边第一个自己没有值,第二个字节有值那么len+3;
.....
*/
for (long x = words[n - 1]; x != 0; x >>>= 8)
len++;
//获取到len的总值后,创建byte数组对象
byte[] bytes = new byte[len];
//通过bytes创建ByteBuffer类对象(其实就是HeapByteBuffer类对象),然后设置排序方式(低位排序和高位排序)
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
//循环,将words中的元素存储到ByteBuffer中(存储的时候采用上面设置的排序方式)
for (int i = 0; i < n - 1; i++)
bb.putLong(words[i]);
//对words中最后一个元素进行处理,一个字节一个字节的存储
for (long x = words[n - 1]; x != 0; x >>>= 8)
bb.put((byte) (x & 0xff));
return bytes;
}
8、toLongArray()函数,代码如下:
/**
* Returns a new long array containing all the bits in this bit set.
*
* <p>More precisely, if
* <br>{@code long[] longs = s.toLongArray();}
* <br>then {@code longs.length == (s.length()+63)/64} and
* <br>{@code s.get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}
* <br>for all {@code n < 64 * longs.length}.
*
* @return a long array containing a little-endian representation
* of all the bits in this bit set
* @since 1.7
*/
public long[] toLongArray() {
return Arrays.copyOf(words, wordsInUse);
}
这个函数用来返回一个long数组,该数组的数组是新创建的,将words数组从0开始,拷贝wordsInUse个到新创建的数组中
9、ensureCapacity()函数,代码如下:
/**
* Ensures that the BitSet can hold enough words.
* @param wordsRequired the minimum acceptable number of words.
*/
private void ensureCapacity(int wordsRequired) {
//如果words的大小小于所需要的
if (words.length < wordsRequired) {
// Allocate larger of doubled size or required size
//扩容最终的大小,最小为原来的两倍
int request = Math.max(2 * words.length, wordsRequired);
//创建新的数组,容量为request,然后将原来的数组拷贝到新的数组中
words = Arrays.copyOf(words, request);
//数组大小不固定的标志
sizeIsSticky = false;
}
}
这个函数用来动态扩容
10、expandTo()函数,代码如下:
/**
* Ensures that the BitSet can accommodate a given wordIndex,
* temporarily violating the invariants. The caller must
* restore the invariants before returning to the user,
* possibly using recalculateWordsInUse().
* @param wordIndex the index to be accommodated.
*/
private void expandTo(int wordIndex) {
int wordsRequired = wordIndex+1;
if (wordsInUse < wordsRequired) {
ensureCapacity(wordsRequired);
wordsInUse = wordsRequired;
}
}
根据数组索引来判断是否要扩容
11、checkRange()函数,代码如下:
/**
* Checks that fromIndex ... toIndex is a valid range of bit indices.
*/
private static void checkRange(int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
if (toIndex < 0)
throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
if (fromIndex > toIndex)
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex +
" > toIndex: " + toIndex);
}
参数验证,确保取值范围符合要求
12、flip()函数,代码如下:
/**
* Sets the bit at the specified index to the complement of its
* current value.
*
* @param bitIndex the index of the bit to flip
* @throws IndexOutOfBoundsException if the specified index is negative
* @since 1.4
*/
public void flip(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
expandTo(wordIndex);
/*^运算符规则为"相同则为0,不相同则为1",
1L << bitIndex(注意这里其实在移位运算的时候是bitIndex对64取模)是将bitIndex位的值设置为1,
例如:
bitIndex为1,那么1L << bitIndex就为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
左移1位后
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010
最后将移位后的二进制值去跟words[wordIndex]去异或运算
这个是什么意思呢,如果在words[wordIndex]上位数为这个值(bitIndex对64取模后的值)的地方有值,也就是1,那么异或后就为0,其他位置有值的变成1,没有值的为0,也就是说其他位的值不变,最终就是将bitIndex对64取模后的值所在的位置的值取反。
*/
words[wordIndex] ^= (1L << bitIndex);
recalculateWordsInUse();
checkInvariants();
}
/**
* Sets each bit from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to the complement of its current
* value.
*
* @param fromIndex index of the first bit to flip
* @param toIndex index after the last bit to flip
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
public void flip(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
expandTo(endWordIndex);
//左移fromIndex位(将WORD_MASK上第fromIndex位的bit设置为0,例如fromIndex为1,表示将右边第一位设置为0)
long firstWordMask = WORD_MASK << fromIndex;
//无符号右移-toIndex位,也就是64-toIndex%64位(将WORD_MASK上无符号右移64-toIndex%64位)
long lastWordMask = WORD_MASK >>> -toIndex;
//如果都在一个words数组元素中
if (startWordIndex == endWordIndex) {
// Case 1: One word
//进行异或操作(相同为0,不同为1)
words[startWordIndex] ^= (firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
//单独对起始的words元素进行取反
words[startWordIndex] ^= firstWordMask;
// Handle intermediate words, if any
//将包含在startWordIndex(不包括)到endWordIndex(不包括)之间的words数组元素全部取反
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] ^= WORD_MASK;
// Handle last word
//单独对最后的words元素进行取反
words[endWordIndex] ^= lastWordMask;
}
recalculateWordsInUse();
checkInvariants();
}
综上所述,flip函数用来将指定的位数取反操作,也就是原来位为0,取反后变成1,原来为1,取反后变成0。
13、set函数,代码如下:
/**
* Sets the bit at the specified index to {@code true}.
*
* @param bitIndex a bit index
* @throws IndexOutOfBoundsException if the specified index is negative
* @since JDK1.0
*/
public void set(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
expandTo(wordIndex);
//将指定的bitIndex位设置成1
words[wordIndex] |= (1L << bitIndex); // Restores invariants
checkInvariants();
}
/**
* Sets the bit at the specified index to the specified value.
*
* @param bitIndex a bit index
* @param value a boolean value to set
* @throws IndexOutOfBoundsException if the specified index is negative
* @since 1.4
*/
public void set(int bitIndex, boolean value) {
if (value)
set(bitIndex);
else
clear(bitIndex);
}
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code true}.
*
* @param fromIndex index of the first bit to be set
* @param toIndex index after the last bit to be set
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
//这个函数与flip函数逻辑差不多,只不过这里采用的是'或'操作,相信了解了flip函数逻辑的就能看明白了,这里不做赘述
public void set(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
// Increase capacity if necessary
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
expandTo(endWordIndex);
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] |= (firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] |= firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = WORD_MASK;
// Handle last word (restores invariants)
words[endWordIndex] |= lastWordMask;
}
checkInvariants();
}
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to the specified value.
*
* @param fromIndex index of the first bit to be set
* @param toIndex index after the last bit to be set
* @param value value to set the selected bits to
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
public void set(int fromIndex, int toIndex, boolean value) {
if (value)
set(fromIndex, toIndex);
else
clear(fromIndex, toIndex);
}
set函数用来将指定的位设置为1
14、clear函数,代码如下:
/**
* Sets the bit specified by the index to {@code false}.
*
* @param bitIndex the index of the bit to be cleared
* @throws IndexOutOfBoundsException if the specified index is negative
* @since JDK1.0
*/
public void clear(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
if (wordIndex >= wordsInUse)
return;
words[wordIndex] &= ~(1L << bitIndex);
recalculateWordsInUse();
checkInvariants();
}
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code false}.
*
* @param fromIndex index of the first bit to be cleared
* @param toIndex index after the last bit to be cleared
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
public void clear(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);
if (startWordIndex >= wordsInUse)
return;
int endWordIndex = wordIndex(toIndex - 1);
if (endWordIndex >= wordsInUse) {
toIndex = length();
endWordIndex = wordsInUse - 1;
}
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] &= ~(firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] &= ~firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = 0;
// Handle last word
words[endWordIndex] &= ~lastWordMask;
}
recalculateWordsInUse();
checkInvariants();
}
/**
* Sets all of the bits in this BitSet to {@code false}.
*
* @since 1.4
*/
public void clear() {
while (wordsInUse > 0)
words[--wordsInUse] = 0;
}
这个函数用来将指定的位设置成0
15、get函数,代码如下:
/**
* Returns the value of the bit with the specified index. The value
* is {@code true} if the bit with the index {@code bitIndex}
* is currently set in this {@code BitSet}; otherwise, the result
* is {@code false}.
*
* @param bitIndex the bit index
* @return the value of the bit with the specified index
* @throws IndexOutOfBoundsException if the specified index is negative
*/
public boolean get(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
checkInvariants();
int wordIndex = wordIndex(bitIndex);
/*
1、首先保证没有越界,否则返回false
2、然后通过1L << bitIndex,将bitIndex位设置为1
3、将2中左移的值和words中索引为wordIndex的值进行&操作
4、如果bitIndex位的值为1,那么&操作后该位的值就为1,此时
对应的words元素值不为0,所以返回true。
如果bitIndex位的值为0,那么&操作后该位的值就为0,此时
对应的words元素值为0,所以返回false。
*/
return (wordIndex < wordsInUse)
&& ((words[wordIndex] & (1L << bitIndex)) != 0);
}
/**
* Returns a new {@code BitSet} composed of bits from this {@code BitSet}
* from {@code fromIndex} (inclusive) to {@code toIndex} (exclusive).
*
* @param fromIndex index of the first bit to include
* @param toIndex index after the last bit to include
* @return a new {@code BitSet} from a range of this {@code BitSet}
* @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
* or {@code toIndex} is negative, or {@code fromIndex} is
* larger than {@code toIndex}
* @since 1.4
*/
public BitSet get(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
checkInvariants();
int len = length();
// If no set bits in range return empty bitset
if (len <= fromIndex || fromIndex == toIndex)
return new BitSet(0);
// An optimization
if (toIndex > len)
toIndex = len;
BitSet result = new BitSet(toIndex - fromIndex);
int targetWords = wordIndex(toIndex - fromIndex - 1) + 1;
int sourceIndex = wordIndex(fromIndex);
boolean wordAligned = ((fromIndex & BIT_INDEX_MASK) == 0);
// Process all words but the last word
for (int i = 0; i < targetWords - 1; i++, sourceIndex++)
result.words[i] = wordAligned ? words[sourceIndex] :
(words[sourceIndex] >>> fromIndex) |
(words[sourceIndex+1] << -fromIndex);
// Process the last word
long lastWordMask = WORD_MASK >>> -toIndex;
result.words[targetWords - 1] =
((toIndex-1) & BIT_INDEX_MASK) < (fromIndex & BIT_INDEX_MASK)
? /* straddles source words */
((words[sourceIndex] >>> fromIndex) |
(words[sourceIndex+1] & lastWordMask) << -fromIndex)
:
((words[sourceIndex] & lastWordMask) >>> fromIndex);
// Set wordsInUse correctly
result.wordsInUse = targetWords;
result.recalculateWordsInUse();
result.checkInvariants();
return result;
}
get函数用来获取某一位是否有效,或者获取某个BitSet类对象的指定范围的数值到一个新的BitSet类对象中
16、nextSetBit()函数,代码如下:
/**
* Returns the index of the first bit that is set to {@code true}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
*
* <p>To iterate over the {@code true} bits in a {@code BitSet},
* use the following loop:
*
* <pre> {@code
* for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
* // operate on index i here
* if (i == Integer.MAX_VALUE) {
* break; // or (i+1) would overflow
* }
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @since 1.4
*/
public int nextSetBit(int fromIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return -1;
long word = words[u] & (WORD_MASK << fromIndex);
while (true) {
if (word != 0)
//numberOfTrailingZeros函数用来返回最低位的1之后0的个数。例如:1101000即104返
//回3
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
if (++u == wordsInUse)
return -1;
word = words[u];
}
}
获取从fromIndex开始第一个设置为1的bit索引值
17、nextClearBit函数,代码如下:
/**
* Returns the index of the first bit that is set to {@code false}
* that occurs on or after the specified starting index.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next clear bit
* @throws IndexOutOfBoundsException if the specified index is negative
* @since 1.4
*/
public int nextClearBit(int fromIndex) {
// Neither spec nor implementation handle bitsets of maximal length.
// See 4816253.
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return fromIndex;
long word = ~words[u] & (WORD_MASK << fromIndex);
while (true) {
if (word != 0)
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
if (++u == wordsInUse)
return wordsInUse * BITS_PER_WORD;
word = ~words[u];
}
}
获取从fromIndex开始第一个设置为0的bit索引值
18、previousSetBit函数,代码如下:
/**
* Returns the index of the nearest bit that is set to {@code true}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* <p>To iterate over the {@code true} bits in a {@code BitSet},
* use the following loop:
*
* <pre> {@code
* for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) {
* // operate on index i here
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous set bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @since 1.7
*/
//统计fromIndex前面第一个为1的值
public int previousSetBit(int fromIndex) {
if (fromIndex < 0) {
if (fromIndex == -1)
return -1;
throw new IndexOutOfBoundsException(
"fromIndex < -1: " + fromIndex);
}
checkInvariants();
int u = wordIndex(fromIndex);
/*这里说明u越界了,所以该函数就变成了统计当前words数组最后一个元素从高位到低为直到遇到第一个为1的位所在的值。
举一个例子:
数组总共有10个,如果最后一个数组为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000
那么此时就是统计上面二进制值从高到低为1的bit所在的值,也就是:
9 * 64 + (64 - 7 * 8 - 1)
上面(64 - 7 * 8 - 1),之所以-1,是因为它是从0开始的,也就是说最低位为0
*/
if (u >= wordsInUse)
return length() - 1;
/*这里WORD_MASK >>> -(fromIndex+1)主要是将fromIndex位设置为1,然后去跟当前的word值去&,举一个例子:
words数组有两个元素,fromIndex为65,该值在数组的第二个元素中,words[1]二进制为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011
此时倒数第二个表示65,然后WORD_MASK >>> -(65+1)即相当于WORD_MASK >>> -66也就是
WORD_MASK >>> 64 - (|-66|%64)最终为WORD_MASK >>> 62。得到的二进制值为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011
此时去和words[1]进行&操作,值为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011
然后进入while循环,返回(1+1)*64 - 1 - 62 = 128 - 63 = 65,所以最终值为65,也就是说65这个值在它之前或者就在它这个位置第一个bit为1的值为65。
如果words[1]的二进制为:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
那么此时就是(1+1)*64 - 1 - 63 = 64,也就是最低位的那个bit所对应的值。
综上来看,它的思想就是:
将该fromIndex所在的bit以及它的低位设置成1,然后去和相应的words数组元素进行&操作(此时fromIndex所在的bit以及它的低位之外的其他bit都变成了0),如果不为0,说明该words元素上有符合要求的bit位,然后查找的规则就是从高位开始查找,直到遇到第一个bit为1的,就是我们要找的
*/
long word = words[u] & (WORD_MASK >>> -(fromIndex+1));
while (true) {
if (word != 0)
return (u+1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word);
if (u-- == 0)
return -1;
word = words[u];
}
}
19、previousClearBit(int fromIndex)函数,代码如下:
/**
* Returns the index of the nearest bit that is set to {@code false}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the previous clear bit, or {@code -1} if there
* is no such bit
* @throws IndexOutOfBoundsException if the specified index is less
* than {@code -1}
* @since 1.7
*/
public int previousClearBit(int fromIndex) {
if (fromIndex < 0) {
if (fromIndex == -1)
return -1;
throw new IndexOutOfBoundsException(
"fromIndex < -1: " + fromIndex);
}
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return fromIndex;
long word = ~words[u] & (WORD_MASK >>> -(fromIndex+1));
while (true) {
if (word != 0)
return (u+1) * BITS_PER_WORD -1 - Long.numberOfLeadingZeros(word);
if (u-- == 0)
return -1;
word = ~words[u];
}
}
这个函数用来获取fromIndex位置或者之前位置中从高到低,第一个为0的bit对应的值,原理与previousSetBit类似,这里不再赘述
20、length()函数,代码如下:
/**
* Returns the "logical size" of this {@code BitSet}: the index of
* the highest set bit in the {@code BitSet} plus one. Returns zero
* if the {@code BitSet} contains no set bits.
*
* @return the logical size of this {@code BitSet}
* @since 1.2
*/
public int length() {
if (wordsInUse == 0)
return 0;
return BITS_PER_WORD * (wordsInUse - 1) +
(BITS_PER_WORD - Long.numberOfLeadingZeros(words[wordsInUse - 1]));
}
这个函数比较简单,不做赘述
21、两个函数,代码如下:
/**
* Returns true if this {@code BitSet} contains no bits that are set
* to {@code true}.
*
* @return boolean indicating whether this {@code BitSet} is empty
* @since 1.4
*/
public boolean isEmpty() {
return wordsInUse == 0;
}
/**
* Returns true if the specified {@code BitSet} has any bits set to
* {@code true} that are also set to {@code true} in this {@code BitSet}.
*
* @param set {@code BitSet} to intersect with
* @return boolean indicating whether this {@code BitSet} intersects
* the specified {@code BitSet}
* @since 1.4
*/
public boolean intersects(BitSet set) {
for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)
if ((words[i] & set.words[i]) != 0)
return true;
return false;
}
这两个函数比较简单
22、cardinality函数,代码如下:
/**
* Returns the number of bits set to {@code true} in this {@code BitSet}.
*
* @return the number of bits set to {@code true} in this {@code BitSet}
* @since 1.4
*/
public int cardinality() {
int sum = 0;
for (int i = 0; i < wordsInUse; i++)
sum += Long.bitCount(words[i]);
return sum;
}
用来获取words数组中每个元素bit为1的总bit数,关于bitCount函数,可以参考另外一个博客的文章,点击查看,另外一篇