/** * 演示java.util.BitSet類的使用 * BitSet類表示自動增長位集合 * @author Sking */ package bitset; import java.util.BitSet; public class BitSetAPITest { public static void main(String[] args){ //BitSet的構造函數 BitSet b1=new BitSet(); BitSet b2=new BitSet(20); //set方法演示 for(int i=3;i<20;i+=3) b1.set(i); System.out.println(b1.toString());//{3, 6, 9, 12, 15, 18} for(int i=2;i<15;i+=2) b1.set(i, false); System.out.println(b1.toString());//{3, 9, 15, 18} b2.set(5, 10); System.out.println(b2.toString());//{5, 6, 7, 8, 9} b2.set(8,14,false); System.out.println(b2.toString());//{5, 6, 7} //flip方法演示 b2.flip(10,15); System.out.println(b2.toString());//{5, 6, 7, 10, 11, 12, 13, 14} b1.flip(15); System.out.println(b1.toString());//{3, 9, 18} //clear方法演示 b2.clear(10); System.out.println(b2.toString());//{5, 6, 7, 11, 12, 13, 14} b2.clear(6, 9); System.out.println(b2.toString());//{5, 11, 12, 13, 14} b2.clear(); System.out.println(b2.toString());//{} //get方法演示 boolean get9=b1.get(9); System.out.println(get9);//true BitSet b3=b1.get(3,10); System.out.println(b3.toString());//{0, 6} b1.set(7,13); b2.set(9,16); System.out.println(b1.toString());//{3, 7, 8, 9, 10, 11, 12, 18} System.out.println(b2.toString());//{9, 10, 11, 12, 13, 14, 15} //位集操作 b1.and(b2); System.out.println(b1.toString());//{9, 10, 11, 12} b2.xor(b1); System.out.println(b2.toString());//{13, 14, 15} b1.or(b2); System.out.println(b1.toString());//{9, 10, 11, 12, 13, 14, 15} b3.set(13,15); b2.andNot(b3); System.out.println(b2.toString());//{15} //設置位操作 System.out.println(b1.cardinality());//7 System.out.println(b2.isEmpty());//false b2.clear(); System.out.println(b2.isEmpty());//true System.out.println(b1.intersects(b3));//true //大小操作 System.out.println(b1.size());//64 System.out.println(b1.length());//16=15+1 //查找 System.out.println(b1.nextSetBit(9));//9 System.out.println(b1.nextClearBit(9));//16 System.out.println(b1.previousSetBit(20));//15 System.out.println(b1.previousClearBit(15));//8 //類型轉化操作 //byte[] b=b1.toByteArray(); //long[] l=b1.toLongArray(); } }
/**
* 藉助BitSet使用篩選法查找指定範圍內的素數
* @param limit 最大正數
*/
public static void searchPrime(int limit){
BitSet bs=new BitSet(limit+1);
//約定:不是素數的在BitSet中將相應的位設置爲true
int size=bs.size();
bs.set(1);
for(int i=4;i<size;i+=2)
bs.set(i);//偶數均不是素數
int finalBit=(int)Math.sqrt(size);
for(int i=2;i<finalBit;i++)
for(int j=2*i;j<size;j+=i)
bs.set(j);
int cout=0;
for(int i=1;i<size;i++){
if(!bs.get(i)){
System.out.printf("%5d",i);
if(++cout==0)
System.out.println();
}
}
System.out.println();
}
/**
* 判斷一個字符串使用了哪些字符,輸出格式爲[字符序列]
* @param s 指定的字符串
* @return 字符串使用的字符序列
*/
public static String whichChars(String s){
BitSet bs=new BitSet();
//字符被使用,則將索引等於字符ASCII值的位置設置爲true
for(int i=0;i<s.length();i++)
bs.set(s.charAt(i));
StringBuffer sb=new StringBuffer();
//輸出格式化
sb.append('[');
int len=bs.length();
for(int i=0;i<len;i++)
if(bs.get(i))
sb.append((char)i);
sb.append(']');
return sb.toString();
}
/**
* 多哈希函數映射的快速查找算法,使用BitSet實現
* 應用在一些需要快速判斷某個元素是否屬於集合,
* 但是並不嚴格要求100%正確的場合,實現大數據處理。
* 應用場景包括:爬蟲中url的存儲。
*
Bloom Filter實現原理:
1.創建BitSet,所有位初始爲false,選擇k個哈希函數
2.將插入值運用k個哈希函數映射到k個二進制位,將其設爲true
3.如果k個二進制爲中有一個有false,則表示原紀錄未被加入過;
如果k個二進制位都有true,則”認爲“原紀錄已被紀錄過,
但是實際上不能100%確定(false positive)。
* @author Sking
*/
package bitset;
import java.util.BitSet;
public class BloomFilter {
/* BitSet初始分配2^24個bit */
private static final int DEFAULT_SIZE = 1 << 25;
/* 不同哈希函數的種子,一般應取質數 */
private static final int[] seeds = new int[] { 5, 7, 11, 13, 31, 37, 61 };
private BitSet bits = new BitSet(DEFAULT_SIZE);
/* 哈希函數對象 */
private SimpleHash[] func = new SimpleHash[seeds.length];
public BloomFilter() {
for (int i = 0; i < seeds.length; i++) {
func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}
// 將字符串標記到bits中
public void add(String value) {
for (SimpleHash f : func) {
bits.set(f.hash(value), true);
}
}
// 判斷字符串是否已經被bits標記
public boolean contains(String value) {
if (value == null) {
return false;
}
boolean ret = true;
for (SimpleHash f : func) {
//如果出現一次的bits.get(f.hash(value))爲false,則原紀錄未被加入過
ret = ret && bits.get(f.hash(value));
}
return ret;
}
/* 哈希函數類,可修改哈希函數,實現更好的優化 */
public static class SimpleHash {
private int cap;//容量
private int seed;//種子
public SimpleHash(int cap, int seed) {
this.cap = cap;
this.seed = seed;
}
// hash函數,採用簡單的加權和hash
public int hash(String value) {
int result = 0;
int len = value.length();
for (int i = 0; i < len; i++) {
result = seed * result + value.charAt(i);
}
return (cap - 1) & result;//截取加權的低log2(cap)位
}
}
}
java.util.BitSet
public class BitSet extends Object implements Cloneable, Serializable
——按需增長的位向量。默認情況下,set 中所有位的初始值都是 false。每個
bitset都包含若干設置位(值爲true的位)。
構造函數
BitSet()
BitSet(int nbits)
普通方法
——1.清除位
void clear()
void clear(int bitIndex)
void clear(int fromIndex,int toIndex)
——分別將全部位| 指定區間內的位(不包括toIndex)| 指定位設置爲false
——2.翻轉位
void flip(int bitIndex)
void flip(int fromIndex,int toIndex)
——將指定位| 指定區間內的位翻轉
——3.設置位
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值,沒有指定則爲true
——4.獲取位
boolean get(int bitIndex)
BitSet get(int fromIndex,int toIndex)
——獲取指定位| 指定區間內的位集
int nextSetBit|previousSetBit(int fromIndex)
——從指定位開始查找下一個|前一個true的位索引,沒有返回-1
int nextClearBit|previousClearBit(int fromIndex)
——從指定位開始查找下一個|前一個false的位索引,沒有返回-1
——5.位集操作《改變的是當前BitSet,而不是參數BitSet》
void and(BitSet set) //與
void or(BitSet set) //或
void xor(BitSet set) //異或
void andNot(BitSet set) //不是與非操作
——清除此 BitSet 中所有的位,其相應的位在指定的 BitSet 中已設置。
——6.設置位操作
int cardinality()
——位集中設置位的個數
boolean isEmpty()
——如果位集中沒有設置位,則返回true
boolean intersects(BitSet set)
——如果兩個位集中存在同一個位置均爲設置位則返回true
——7.大小操作
int size() //實際分配空間
int length() //邏輯大小,最高設置位的索引加1
——8.打印操作
String toString()
——格式:{設置爲true的位索引列表,用,分隔}