什么是布隆过滤器
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,由伯顿·布隆(Burton Howard Bloom)在1970年提出。它主要用于测试一个元素是否属于某个集合,尽管存在一定的误报率(false positive rate),但不会产生误删(false negative),即如果布隆过滤器报告一个元素可能在集合中,这可能是错误的;但如果它报告元素肯定不在集合中,那一定是正确的。
总结: 布隆过滤器是一种数据结构,用于快速检索一个元素是否可能存在于一个集合(bit 数组)中。
为什么可能存在集合中可能是错误的
它的基本原理是利用多个哈希函数,将一个元素映射成多个位,然后将这些位设置为 1。当查询一个元素时,如果这些位都被设置为 1,则认为元素可能存在于集合中,否则肯定不存在。
所以,布隆过滤器可以准确的判断一个元素是否一定不存在,但是因为哈希冲突的存在,所以他没办法判断一个元素一定存在。只能判断可能存在。
布隆过滤器的工作过程
1.初始化布隆过滤器
在初始化布隆过滤器时,需要指定集合的大小和误判率。布隆过滤器内部包含一个bit数组和多个哈希函数,每个哈希函数都会生成一个索引值。
2.添加元素到布隆过滤器
要将一个元素添加到布隆过滤器中,首先需要将该元素通过多个哈希函数生成多个索引值,然后将这些索引值对应的位设置为 1。如果这些索引值已经被设置为 1,则不需要再次设置。
3.查询元素是否存在于布隆过滤器中
要查询一个元素是否存在于布隆过滤器中,需要将该元素通过多个哈希函数生成多个索引值,并判断这些索引值对应的位是否都被设置为 1。如果这些位都被设置为 1,则认为元素可能存在于集合中,否则肯定不存在。
应用场景
布隆过滤器因为他的效率非常高,所以被广泛的使用,比较典型的场景有以下几个:
1网页爬虫:爬虫程序可以使用布隆过滤器来过滤掉已经爬取过的网页,避免重复爬取和浪费资源。
2缓存系统:缓存系统可以使用布隆过滤器来判断一个查询是否可能存在于缓存中,从而减少查询缓存的次数,提高查询效率。布隆过滤器也经常用来解决缓存穿透的问题。
3分布式系统:在分布式系统中,可以使用布隆过滤器来判断一个元素是否存在于分布式缓存中,避免在所有节点上进行查询,减少网络负载。
4垃圾邮件过滤:布隆过滤器可以用于判断一个邮件地址是否在垃圾邮件列表中,从而过滤掉垃圾邮件。
5黑名单过滤:布隆过滤器可以用于判断一个IP地址或手机号码是否在黑名单中,从而阻止恶意请求。
Java中可以使用第三方库来实现布隆过滤器,常见的有Google Guava库和Apache Commons库以及Redis。
Guava
public class BloomFilterExample {public static void main(String[] args) {// 创建布隆过滤器,预计插入100个元素,误判率为0.01BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(), 100, 0.01);// 插入元素bloomFilter.put("bate");bloomFilter.put("666");bloomFilter.put("王星星");// 判断元素是否存在System.out.println(bloomFilter.mightContain("bate")); // trueSystem.out.println(bloomFilter.mightContain("王星")); // false}
}
Apache Commons
public class BloomFilterExample {public static void main(String[] args) {// 创建布隆过滤器,预计插入100个元素,误判率为0.01BloomFilter<String> bloomFilter = new BloomFilter<>(HashFunctionIdentity.hashFunction(StringUtils::hashCode), 100, 0.01);// 插入元素bloomFilter.put("bate");bloomFilter.put("666");bloomFilter.put("王星星");// 判断元素是否存在System.out.println(bloomFilter.mightContain("bate")); // trueSystem.out.println(bloomFilter.mightContain("王星")); // false}
}