一个低配版BloomFilter
public class MyBloomFilter {
// 后面hash函数会用到,用来生成不同的hash值,可以随便给,但别给奇数
private final int[] ints = {6, 8, 16, 38, 58, 68};
// 统计当前对象数量
private Integer currentBeanCount = 0;
// 你的布隆过滤器容量
private int DEFAULT_SIZE = Integer.MAX_VALUE;
// bit数组,用来存放结果
private final BitSet bitSet = new BitSet(DEFAULT_SIZE);
public MyBloomFilter() {
}
public MyBloomFilter(int size) {
if (size > Integer.MAX_VALUE) throw new RuntimeException("size is too large");
if (size <= (2 << 8)) throw new RuntimeException("size is too small");
DEFAULT_SIZE = size;
}
// 获取当前过滤器的对象数量
public Integer getCurrentBeanCount() {
return currentBeanCount;
}
// 计算出key的hash值,并将对应下标置为1
public void push(Object key) {
Arrays.stream(ints).forEach(i -> bitSet.set(hash(key, i)));
currentBeanCount++;
}
// 判断key是否存在,true不一定说明key存在,但是false一定说明不存在
public boolean contain(Object key) {
boolean result = true;
for (int i : ints) {
result = result && bitSet.get(hash(key, i));
}
return result;
}
// hash算法,借鉴了hashmap的算法,利用i对同个key生成一组不同的hash值
private int hash(Object key, int i) {
int h;
int index = key == null ? 0 : (DEFAULT_SIZE - 1 - i) & ((h = key.hashCode()) ^ (h >>> 16));
return index > 0 ? index : -index;
}
}
它在用作判断对象 是否存在 时有误判率,误判率随着对象数量增加而增加
但是用作判断对象 是否不存在 时,没有误判率
一亿条数据去重
public static void main(String[] args) {
//实例化
MyBloomFilter filter = new MyBloomFilter();
for (int i = 0; i < 20; i++) {
//push到BloomFilter
getPersonList(500000).forEach(person -> filter.push(person));
}
//push一个确定的对象
filter.push(getFixedPerson(now));
//判断这个对象是否存在
long start = System.currentTimeMillis();
System.out.println(filter.contain(getFixedPerson(now)));
long end = System.currentTimeMillis() - start;
System.out.println("bloomFilter内对象数量:" + filter.getCurrentBeanCount());
System.out.println("耗时(ms):" + end + ",消耗内存(M):" + (ObjectSizeCalculator.getObjectSize(filter) / (1024 * 1024)));
}
原理
就是通过对比hash算法计算出来的下标,但注意,是对比一组,而不是一次,一次hash结果只对应一个下标
把同一个key进行多次hash运算,将hash出来的下标放入数组,数组默认全为0,放入元素后该下标就为1,后面判断是否存在元素的时候也是进行同样次数的hash运算,看下结果对应的所有下标是否全为1,若全为1,则代表该key可能存在,若存在不为1的,则说明该key一定不存在;
默认bit数组:[0,0,0,0,0,0]
比方说有个key计算出的一组hash下标是0,2,5
对应位bit数组:[1,0,1,0,0,1]
判断某个未知key是否存在时候,假设我们计算出来的下标是0,2,4
对应位数组:[1,0,1,0,1,0]
此时位数组内5对应下标值为0,而已知key位数组的5对应下标位1,说明这两个key一定不同
相反,如果某个key计算出来的下标为[1,0,1,0,0,1],只能说这个key可能存在,因为这几个位置可能是其它key计算出来的
摘自:https://blog.csdn.net/qq_33709582/article/details/122046773