一、布隆过滤器的工作原理
布隆过滤器本身是一个很长的二进制向量,既然是二进制的向量,那么显而易见的,存放的不是0,就是1。
新建一个16位的布隆过滤器,如图
有一个对象,我们通过
方式一计算他的hash值,得到hash = 2
方式二计算他的hash值,得到hash = 9
方式三计算他的hash值,得到hash = 5
通过三个方法计算得到三个数值,我们把这三个数值对应的布隆过滤器向量值改为1,表明该位置有值。
第二个对象,加入得到值1 6 3,就把1 6 3 改为1
对于布隆过滤器本身来说,并没有存储任何数据,只是计算该数据的位置,然后存储向量值
那么,如果需要判断某个数据是否存在于布隆过滤器,就只需要判断计算出来的所有向量值是否都为1即可。
但是,当存储的数据向量不断增多,就可能会出现,2 9 5 向量值都为1,但是实际上没有这个数据的情况,这样就导致了,布隆过滤器只能判断某个数据一定不存在,但是不能保证某个数据一定存在。
另外,因为一个向量位置可能被多个对象映射,所以,布隆过滤器无法删除数据
二、布隆过滤器的设计
如果向量长度太短,会导致误判率直线上升。
如果向量太长,会浪费大量内存。
如果计算次数过多,会占用计算资源,且很容易很快就把过滤器填满。
三、代码实现
POM文件依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version></dependency>
</dependency>
测试代码
public static void main(String... args){
/** * 创建一个插入对象为一亿,误报率为0.01%的布隆过滤器 */
BloomFilter<CharSequence> bloomFilter =
BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 100000000, 0.0001);
bloomFilter.put("121");
bloomFilter.put("122");
bloomFilter.put("123");
System.out.println(bloomFilter.mightContain("121"));
}