/** * 演示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.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的位索引列表,用,分隔}