基本原理
BitSet是位操作的對象,值隻有0或1即false和true,内部維護了一個long數組,初始隻有一個long,是以BitSet最小的size是64,當随着存儲的元素越來越多,BitSet内部會動态擴充,最終内部是由N個long來存儲,這些針對操作都是透明的。
用1位來表示一個資料是否出現過,0為沒有出現過,1表示出現過。使用用的時候既可根據某一個是否為0表示,此數是否出現過。
一個1G的空間,有 8*1024*1024*1024=8.58*10^9bit,也就是可以表示85億個不同的數
40億個整數中找到那個唯一重複的數字
import java.util.BitSet;
public class BitSet2 {
public static void main(String[] args) {
BitSet bitSet=new BitSet();
int[] nums={,,,,,,};
for (int num : nums) {
if(bitSet.get(num)){
System.out.println(num);
break;
}else {
bitSet.set(num);
}
}
}
}
源碼分析:
/**
* 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) {//62
if (bitIndex < )
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);//wordIndex /2^6=0;0号桶
expandTo(wordIndex);//擴容2倍
//words數組,,,1L是Long型,64位,63-0,左移62位,即010000000000....
words[wordIndex] |= (L << bitIndex); // Restores invariants
checkInvariants();
}
/**
* 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 < )
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
checkInvariants();
int wordIndex = wordIndex(bitIndex);//wordIndex =0号桶
return (wordIndex < wordsInUse)
&& ((words[wordIndex] & (L << bitIndex)) != );
}
/**
(wordIndex < wordsInUse)//首先位桶足夠
((words[wordIndex] & (1L << bitIndex)) != 0);
等價于(words[wordIndex] & (1L << bitIndex%64)) != 0
bitIndex%64即bitIndex取低6位
然後在1左移bitIndex取低6位之後的結果
如果bitIndex=1025
wordIndex =1025/2^6=16号桶
words[wordIndex]=words[16]
1L << bitIndex即1L << bitIndex%64即 bitIndex取低六位000001=1,再1L<<1,即00...10
即1025在第16号桶的第1個比特位上,,,,,63。。。。0
*/