本文共 2739 字,大约阅读时间需要 9 分钟。
ss
添加进一个文件,然后我们怎么用布隆过滤器来标识一个ss
字符串是否已经添加进了文件呢?ss
进行hash得到一个数组长度范围内的一个整数值,即bytes数组的下标,然后将此位置上的0更改为1,代表ss
被添加进了文件ss
添加进去aa
,bb
,cc
添加进入aa
与cc
的一个整数返回值一样,所以同一个位置被标记了两次,如果这时候只是每个字符串返回一个整数值的话,就会出现上面说的模糊的状态的情况zz
,我们知道这个是没有添加进去的zz
的时候,同样是应用三次算法,返回三个整数值,有一处发生了重叠,而另外两处是没有发生重叠的,只要有一个没有发生重叠也就说明zz
是没有添加进去过的aa
的添加状态aa
是可能被添加进去过的,那么为什么说是可能呢,虽然算法可能会返回不同的计算值,而且我们利用了"联合的方式"来确保不造成模糊的状态,但是依旧是无法保证一个元素对应一个位置的,还是有可能发生重叠的,虽然概率很小,网上的说法是万分之一这个过滤方法可以说明一个值一定不在这里面又是为什么呢,因为算法是不会出错的,过滤器内被标记的位置都是相同的算法计算得出的,算法并不会中途发生改变,所以这个一个函数式的过程,即输入一个相同的值肯定会返回值对应的相同的结果(即如下一个简单的代码演示的效果,输入1,永远会返回2),所以如果数组内的对应位置没有发生标记行为,那么是肯定没有这个值的
private int getNum(int i){ return i + 1;}
过滤器的应用:我们从上面可以看到算法的优势就是相当迅速的判断一个值是否在这里面,这也就可以应用在
Google的包中提供了一个Bloom过滤的实现,我们稍微用一下
com.google.guava guava 27.0.1-jre
import com.google.common.hash.BloomFilter;import com.google.common.hash.Funnel;import com.google.common.hash.Funnels;import java.nio.charset.Charset;public class BloomFilterTest { public static void main(String[] args) { //z字符串的编解码 Charset charset = Charset.forName("UTF8"); //你预计的元素的个数 long expectElementNum = 1000; //你希望的出错率 double expectErrorRate = 0.1; //这有很多类型比如,integerFunnel,doubleFunnel... Funnel funnel = Funnels.stringFunnel(charset); BloomFilter bloomFilter = BloomFilter.create(funnel, expectElementNum, expectErrorRate); bloomFilter.put("aa"); bloomFilter.put("dd"); bloomFilter.put("bb"); bloomFilter.put("cc"); bloomFilter.put("ee"); bloomFilter.put("ff"); bloomFilter.put("gg"); bloomFilter.put("hh"); bloomFilter.put("kk"); bloomFilter.put("ii"); bloomFilter.put("jj"); //测试 : true System.out.println(bloomFilter.test("bb")); }}
转载地址:http://wbjka.baihongyu.com/