BitSet 用法总结

BitSet基本介绍

  • BitSet是线程不安全的
  • BitSet的初始大小是64位的,每次动态扩容为之前的2倍或者可以满足现在大小中最大的

BitSet源码分析

  • BitSet存储的基本数据结构(一个long型的数组)
    /** * The internal field corresponding to the serialField "bits". */
    private long[] words;
    
  • BitSet的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);
    }
    
  • BitSet的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动态扩容方法的实现

    • 初始大小,2^6 = 64位(一个long型数据)
      private final static int ADDRESS_BITS_PER_WORD = 6;
      
    • 使用long[]数组的数量,即使用的word的数量,一个word64位

      private transient int wordsInUse = 0;
      
    • 计算需要多少个word

      private static int wordIndex(int bitIndex) { 
          return bitIndex >> ADDRESS_BITS_PER_WORD;
      }
      
    • 检查是否需要扩容

      private void expandTo(int wordIndex) { 
          int wordsRequired = wordIndex+1; 
          if (wordsInUse < wordsRequired) { 
              ensureCapacity(wordsRequired); 
              wordsInUse = wordsRequired; 
          }
      }
      
    • 容量扩充为之前的两倍或者满足现在容量最大的(long []数组扩充)
      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; 
          }
      }
      
    • 好好理解一下核心的这句扩容语句

      int request = Math.max(2 * words.length, wordsRequired);
      
    • Arrays内部使用System.arraycopy实现扩容,需要重新new一个long[]

      public static long[] copyOf(long[] original, int newLength) {
          long[] copy = new long[newLength]; 
          System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); 
          return copy;
      }
      
  • BitSet 统计true的数量实现方法(cardinality方法)

    public int cardinality() { 
      int sum = 0; 
      for (int i = 0; i < wordsInUse; i++) 
      sum += Long.bitCount(words[i]); 
      return sum;
    }
    
  • nextSetBit实现方法

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

BitSet Demo

public static void test1() { 
    BitSet bitSet = new BitSet(); 
    bitSet.set(23); 
    System.out.println("bitSet size:" + bitSet.size()); bitSet.set(54); 
    System.out.println("bitSet size:" + bitSet.size()); bitSet.set(67); 
    System.out.println("bitSet size:" + bitSet.size()); bitSet.set(320);     
    System.out.println("bitSet size:" + bitSet.size()); 
    System.out.println("The true numbers: " + bitSet.cardinality()); 
    System.out.println("The nextClearBit: " + bitSet.nextClearBit(0)); 
    System.out.println("The nextSetBit: " + bitSet.nextSetBit(0)); 
    bitSet.xor(bitSet); 
    System.out.println("The true numbers: " + bitSet.cardinality()); 
    System.out.println("12's numberOfTrailingZeros: " +  Long.numberOfTrailingZeros(12));}
}

输出结果为:

bitSet size:64
bitSet size:64
bitSet size:128
bitSet size:384
The true numbers: 4
The nextClearBit: 0
The nextSetBit: 23
The true numbers: 0
12's numberOfTrailingZeros: 2

BitSet 基本方法介绍

返回类型 方法名称 描述
void and(BitSet set) 按位进行与操作
void andNot(BitSet set) 按位进行清除操作
void or(BitSet set) 按位进行或操作
void xor(BitSet set) 按位进行异或操作
void cardinality() 位图中true的数量,即被设置的位的数量
int nextClearBit(int fromIndex) 位图中从fromIndex开始后面第一个为false的位的索引值
int nextSetBit(int fromIndex) 位图中从fromIndex开始后面第一个为true的位的索引值
int previousClearBit(int fromIndex) 位图中从fromIndex开始前面第一个为false的位的索引值
int previousSetBit(int fromIndex) 位图中从fromIndex开始前面第一个为true的位的索引值
boolean intersects(set) 两个位图中存在同样为true的位
void clear() 位图中所有位全部置为false
void clear(int bitIndex) 位图中bitIndex这个位置设置false
void clear(int fromIndex, int toIndex) 位图中从fromIndex到toIndex位置的位全部设置为false
void flip(int bitIndex) 位图中的bitIndex位数值反转 0->1 1->0
void flip(int fromIndex, int toIndex)
void set(int bitIndex)
void set(int bitIndex, boolean value)
void set(int fromIndex, int toIndex)
void set(int fromIndex, int toIndex, boolean value)
boolean get(int bitIndex)
BitSet get(int fromIndex, int toIndex)

BitSet解决LeetCode 41题方法

public int firstMissingPositive(int[] nums) { 
    BitSet set = new BitSet(); 
    for (int i = 0; i < nums.length; i++) { 
        if (nums[i] >= 0) {
            set.set(nums[i]); 
        }
    } 
    return set.nextClearBit(1);
}

results matching ""

    No results matching ""