赞
踩
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
时间复杂度低,增加和查询元素的时间复杂为O(N),(N为哈希函数的个数,通常情况比较小)
保密性强,布隆过滤器不存储元素本身
存储空间小,如果允许存在一定的误判,布隆过滤器是非常节省空间的(相比其他数据结构如Set集合)
有点一定的误判率,但是可以通过调整参数来降低
无法获取元素本身
很难删除元素
布隆过滤器可以告诉我们 “某样东西一定不存在或者可能存在”,也就是说布隆过滤器说这个数不存在则一定不存,布隆过滤器说这个数存在可能不存在(误判率)
将要添加的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置,然后将这k个位置设置为1。
将要查询的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置,如果这k个位置中有一个位置为0,则此元素一定不存在集合中,如果这k个位置全部为1,则这个元素可能存在。
package BloomFilter; import java.util.BitSet; /** * @author SunYuHang * @date 2023-01-01 12:09 * @ClassName : MyBloomFilter //类名 */ class SimpleHash{ public int cap; public int seed; public SimpleHash(int cap,int seed){ this.cap = cap; this.seed = seed; } //根据seed不同 创建不同的哈希函数 final int hash(String key){ int h; return (key == null)?0:(seed*(cap-1))&(h=key.hashCode())^(h>>>16); } } public class MyBloomFilter { public static final int DEFAULT_SIZE = 1<<20; //位图 public BitSet bitSet; //记录存了多少个数据 public int usedSize; public static final int[] seeds = {5,7,11,13,27,33}; public SimpleHash[] simpleHashes; public MyBloomFilter(){ bitSet = new BitSet(); simpleHashes = new SimpleHash[seeds.length]; for (int i = 0; i <simpleHashes.length; i++) { simpleHashes[i] = new SimpleHash(DEFAULT_SIZE,seeds[i]); } } }
/** * 添加元素 到布隆过滤器 * @param val */ public void add(String val) { //让X个哈希函数 分别处理当前的数据 for (SimpleHash simpleHash : simpleHashes) { int index = simpleHash.hash(val); //把他们 都存储在位图当中即可 bitSet.set(index); } } /** * 是否包含val ,这里会存在一定的误判的 * @param val * @return */ public boolean contains(String val) { //val 一定 也是通过这个几个哈希函数去 看对应的位置 for (SimpleHash simpleHash : simpleHashes) { int index = simpleHash.hash(val); //只要有1个为 0 那么一定不存在 boolean flg = bitSet.get(index); if(!flg) { return false; } } return true; }
public static void main(String[] args) {
MyBloomFilter myBloomFilter = new MyBloomFilter();
myBloomFilter.add("hello");
myBloomFilter.add("hello2");
myBloomFilter.add("bit");
myBloomFilter.add("haha");
System.out.println(myBloomFilter.contains("hello"));
System.out.println(myBloomFilter.contains("hello3"));
System.out.println(myBloomFilter.contains("he"));
}
首先在pom引入依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
然后就可以测试啦:
private static int size = 1000000;//预计要插入多少数据 private static double fpp = 0.01;//期望的误判率 private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp); public static void main(String[] args) { //插入数据 for (int i = 0; i < 1000000; i++) { bloomFilter.put(i); } int count = 0; for (int i = 1000000; i < 2000000; i++) { if (bloomFilter.mightContain(i)) { count++; System.out.println(i + "误判了"); } } System.out.println("总共的误判数:" + count); }
代码简单分析:
我们定义了一个布隆过滤器,有两个重要的参数,分别是 我们预计要插入多少数据,我们所期望的误判率,误判率不能为0。
我向布隆过滤器插入了0-1000000,然后用1000000-2000000来测试误判率。
运行结果:
............
1999501误判了
1999567误判了
1999640误判了
1999697误判了
1999827误判了
1999942误判了
总共的误判数:10314
现在总共有100万数据是不存在的,误判了10314次,我们计算下误判率
和我们定义的期望误判率0.01相差无几。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。