/** * 演示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
/**
* 多哈希函数映射的快速查找算法,使用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.lang.Object
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的位索引列表,用,分隔}