BitSet 源码

89 阅读6分钟

package java.util;

import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.LongBuffer; import java.util.stream.IntStream; import java.util.stream.StreamSupport;

/**

  • @author Arthur van Hoff

  • @author Michael McCloskey

  • @author Martin Buchholz

  • @since JDK1.0 / public class BitSet implements Cloneable, java.io.Serializable { /

    • 常量 */ private final static int ADDRESS_BITS_PER_WORD = 6; // 1左移6位 64 private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; // 63 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), };

    /**

    • long 类型数组 */ private long[] words;

    /**

    • 表示当前数组有多少个8个字节 */ 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. */ private transient boolean sizeIsSticky = false;

    /* use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = 7997698588986878753L;

    /**

    • Given a bit index, return word index containing it.
    • 默认bitIndex =63 位运算 bitIndex传入的值 比如 63 60 long =8字节 有64位 可以存储0-63的整数
    • 用63/64 商等于 存放的值是在哪个下标数组中 比如这个等于 0 表示 在index=0 的数组中 63/64 余数63表示 就知道它在此下标的哪个位置
    • // 确定传入的值在数组哪个下标中 第二步 确定 具体在下标数组哪个位置
    • 这个方法确定传入的值在数组index 那个下标中 */ private static int wordIndex(int bitIndex) { // 63/64 =0 return bitIndex >> ADDRESS_BITS_PER_WORD; }

    /**

    • 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); }

    /**

    • 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 }

    /**

    • 创建long数组 默认是只能存放一个元素的long数组 long[] words = new Long[1]; */ public BitSet() { //BITS_PER_WORD=64; initWords(BITS_PER_WORD); sizeIsSticky = false; }

    /**

    • 创建指定大小的数组 */ public BitSet(int nbits) { // 传入负数 直接抛出异常 if (nbits < 0) throw new NegativeArraySizeException("nbits < 0: " + nbits);

      // 创建数组 initWords(nbits); sizeIsSticky = true; }

    /**

    • 创建数组 */ private void initWords(int nbits) { // 创建long数组 words = new long[wordIndex(nbits-1) + 1]; }

    /**

    • 创建传入的long数组 / private BitSet(long[] words) { this.words = words; /* 8个字节=1个wordsInUse */ this.wordsInUse = words.length; checkInvariants(); }

    /**

    • Returns a new bit set containing all the bits in the given long array.
    • More precisely,


    • {@code BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}

    • for all {@code n < 64 * longs.length}.
    • 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; for (n = longs.length; n > 0 && longs[n - 1] == 0; n--) ; 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.
    • More precisely,


    • {@code BitSet.valueOf(lb).get(n) == ((lb.get(lb.position()+n/64) & (1L<<(n%64))) != 0)}

    • for all {@code n < 64 * lb.remaining()}.
    • 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 */ public static BitSet valueOf(LongBuffer lb) { lb = lb.slice(); int n; for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--) ; long[] words = new long[n]; lb.get(words); return new BitSet(words); }

    /**

    • Returns a new bit set containing all the bits in the given byte array.
    • More precisely,


    • {@code BitSet.valueOf(bytes).get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}

    • for all {@code n < 8 * bytes.length}.
    • 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) { 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.
    • More precisely,


    • {@code BitSet.valueOf(bb).get(n) == ((bb.get(bb.position()+n/8) & (1<<(n%8))) != 0)}

    • for all {@code n < 8 * bb.remaining()}.
    • 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); }

    /**

    • Returns a new byte array containing all the bits in this bit set.
    • More precisely, if


    • {@code byte[] bytes = s.toByteArray();}

    • then {@code bytes.length == (s.length()+7)/8} and

    • {@code s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}

    • 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]; int len = 8 * (n-1); for (long x = words[n - 1]; x != 0; x >>>= 8) len++; byte[] bytes = new byte[len]; ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < n - 1; i++) bb.putLong(words[i]); for (long x = words[n - 1]; x != 0; x >>>= 8) bb.put((byte) (x & 0xff)); return bytes; }

    /**

    • Returns a new long array containing all the bits in this bit set.
    • More precisely, if


    • {@code long[] longs = s.toLongArray();}

    • then {@code longs.length == (s.length()+63)/64} and

    • {@code s.get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}

    • 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); }

    /**

    • Ensures that the BitSet can hold enough words.
    • @param wordsRequired the minimum acceptable number of words. */ private void ensureCapacity(int wordsRequired) { if (words.length < wordsRequired) { // Allocate larger of doubled size or required size int request = Math.max(2 * words.length, wordsRequired); words = Arrays.copyOf(words, request); sizeIsSticky = false; } }

    /**

    • 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; } }

    /**

    • 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); }

    /**

    • 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);

      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);

      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
       words[endWordIndex] ^= lastWordMask;
      

      }

      recalculateWordsInUse(); checkInvariants(); }

    /**

    • @param bitIndex 添加的值
    • @since JDK1.0 */ public void set(int bitIndex) { if (bitIndex < 0) { throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); } // 1、确定数组下标位置 int wordIndex = wordIndex(bitIndex); // 添加进去的值有可能不够所以要扩容 expandTo(wordIndex); // 2、与运算 把相应位置数据 替换成1 增加成功 words[wordIndex] |= (1L << bitIndex); checkInvariants(); }

    /**

    • 增加元素 或者替换元素
    • @param bitIndex 要增加的数据
    • @param value 判断操作方法 true 增加 fasle 删除
    • @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 */ 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); }

    /** 删除元素

    • @param bitIndex 要删除的值
    • @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(); }

    /**

    • 把数组中的值设置为0
    • @since 1.4 */ public void clear() { while (wordsInUse > 0) words[--wordsInUse] = 0; }

    /**

    • 判断元素bitIndex是否在数组中

    • @param bitIndex 传入的数据

    • @return */ 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); }

    /**

    • 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; }

    /**

    • 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.

    • To iterate over the {@code true} bits in a {@code BitSet},

    • use the following loop:

    •  {@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
      
    • }
      
    • }}

    • @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) return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); if (++u == wordsInUse) return -1; word = words[u]; } }

    /**

    • 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]; } }

    /**

    • 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.

    • To iterate over the {@code true} bits in a {@code BitSet},

    • use the following loop:

    •  {@code
      
      
    • for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) {

    • // operate on index i here
      
    • }}

    • @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 */ public int previousSetBit(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 length() - 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]; } }

    /**

    • 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]; } }

    /**

    • 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])); }

    /**

    • 没有存放任何元素
    • @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; }

    /**

    • 统计有多少个1 其实就是存放了多少数据
    • @return
    • @since 1.4 */ public int cardinality() { int sum = 0; for (int i = 0; i < wordsInUse; i++) sum += Long.bitCount(words[i]); return sum; }

    /**

    • Performs a logical AND of this target bit set with the

    • argument bit set. This bit set is modified so that each bit in it

    • has the value {@code true} if and only if it both initially

    • had the value {@code true} and the corresponding bit in the

    • bit set argument also had the value {@code true}.

    • @param set a bit set */ public void and(BitSet set) { if (this == set) return;

      while (wordsInUse > set.wordsInUse) words[--wordsInUse] = 0;

      // Perform logical AND on words in common for (int i = 0; i < wordsInUse; i++) words[i] &= set.words[i];

      recalculateWordsInUse(); checkInvariants(); }

    /**

    • Performs a logical OR of this bit set with the bit set

    • argument. This bit set is modified so that a bit in it has the

    • value {@code true} if and only if it either already had the

    • value {@code true} or the corresponding bit in the bit set

    • argument has the value {@code true}.

    • @param set a bit set */ public void or(BitSet set) { if (this == set) return;

      int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);

      if (wordsInUse < set.wordsInUse) { ensureCapacity(set.wordsInUse); wordsInUse = set.wordsInUse; }

      // Perform logical OR on words in common for (int i = 0; i < wordsInCommon; i++) words[i] |= set.words[i];

      // Copy any remaining words if (wordsInCommon < set.wordsInUse) System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, wordsInUse - wordsInCommon);

      // recalculateWordsInUse() is unnecessary checkInvariants(); }

    /**

    • Performs a logical XOR of this bit set with the bit set

    • argument. This bit set is modified so that a bit in it has the

    • value {@code true} if and only if one of the following

    • statements holds:

      • The bit initially has the value {@code true}, and the
      • corresponding bit in the argument has the value {@code false}.
        
      • The bit initially has the value {@code false}, and the
      • corresponding bit in the argument has the value {@code true}.
        
    • @param set a bit set */ public void xor(BitSet set) { int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);

      if (wordsInUse < set.wordsInUse) { ensureCapacity(set.wordsInUse); wordsInUse = set.wordsInUse; }

      // Perform logical XOR on words in common for (int i = 0; i < wordsInCommon; i++) words[i] ^= set.words[i];

      // Copy any remaining words if (wordsInCommon < set.wordsInUse) System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, set.wordsInUse - wordsInCommon);

      recalculateWordsInUse(); checkInvariants(); }

    /**

    • Clears all of the bits in this {@code BitSet} whose corresponding

    • bit is set in the specified {@code BitSet}.

    • @param set the {@code BitSet} with which to mask this

    •     {@code BitSet}
      
    • @since 1.2 */ public void andNot(BitSet set) { // Perform logical (a & !b) on words in common for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--) words[i] &= ~set.words[i];

      recalculateWordsInUse(); checkInvariants(); }

    /**

    • hashcode方法 */ public int hashCode() { long h = 1234; for (int i = wordsInUse; --i >= 0; ) h ^= words[i] * (i + 1);

      return (int)((h >> 32) ^ h); }

    /**

    • 判断数组中有多少位 数组大小*64位 */ public int size() { // return words.length * BITS_PER_WORD; }

    /**

    • 判断是否相等 */ public boolean equals(Object obj) { if (!(obj instanceof BitSet)) return false; if (this == obj) return true;

      BitSet set = (BitSet) obj;

      checkInvariants(); set.checkInvariants();

      if (wordsInUse != set.wordsInUse) return false;

      // Check words in use by both BitSets for (int i = 0; i < wordsInUse; i++) if (words[i] != set.words[i]) return false;

      return true; }

    /**

    • 浅复制 */ public Object clone() { if (! sizeIsSticky) trimToSize();

      try { BitSet result = (BitSet) super.clone(); result.words = words.clone(); result.checkInvariants(); return result; } catch (CloneNotSupportedException e) { throw new InternalError(e); } }

    /**

    • 缩小内存 */ private void trimToSize() { if (wordsInUse != words.length) { words = Arrays.copyOf(words, wordsInUse); checkInvariants(); } }

    /**

    • Save the state of the {@code BitSet} instance to a stream (i.e.,

    • serialize it). */ private void writeObject(ObjectOutputStream s) throws IOException {

      checkInvariants();

      if (! sizeIsSticky) trimToSize();

      ObjectOutputStream.PutField fields = s.putFields(); fields.put("bits", words); s.writeFields(); }

    /**

    • Reconstitute the {@code BitSet} instance from a stream (i.e.,

    • deserialize it). */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {

      ObjectInputStream.GetField fields = s.readFields(); words = (long[]) fields.get("bits", null);

      // Assume maximum length then find real length // because recalculateWordsInUse assumes maintenance // or reduction in logical size wordsInUse = words.length; recalculateWordsInUse(); sizeIsSticky = (words.length > 0 && words[words.length-1] == 0L); // heuristic checkInvariants(); }

    /**

    • tostring 获取存入数值字符串拼接 */ public String toString() { checkInvariants();

      int numBits = (wordsInUse > 128) ? cardinality() : wordsInUse * BITS_PER_WORD; StringBuilder b = new StringBuilder(6*numBits + 2); b.append('{');

      int i = nextSetBit(0); if (i != -1) { b.append(i); while (true) { if (++i < 0) break; if ((i = nextSetBit(i)) < 0) break; int endOfRun = nextClearBit(i); do { b.append(", ").append(i); } while (++i != endOfRun); } }

      b.append('}'); return b.toString(); }

    /**

    • Returns a stream of indices for which this {@code BitSet}

    • contains a bit in the set state. The indices are returned

    • in order, from lowest to highest. The size of the stream

    • is the number of bits in the set state, equal to the value

    • returned by the {@link #cardinality()} method.

    • The bit set must remain constant during the execution of the

    • terminal stream operation. Otherwise, the result of the terminal

    • stream operation is undefined.

    • @return a stream of integers representing set indices

    • @since 1.8 */ public IntStream stream() { class BitSetIterator implements PrimitiveIterator.OfInt { int next = nextSetBit(0);

       @Override
       public boolean hasNext() {
           return next != -1;
       }
      
       @Override
       public int nextInt() {
           if (next != -1) {
               int ret = next;
               next = nextSetBit(next+1);
               return ret;
           } else {
               throw new NoSuchElementException();
           }
       }
      

      }

      return StreamSupport.intStream( () -> Spliterators.spliterator( new BitSetIterator(), cardinality(), Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED), Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED, false); } }