Guava布隆过滤器(boomfilter)使用简介

1 布隆过滤器简介

布隆过滤器是一种空间利用率较高的概率型数据结构,用来测试一个元素是否在集合中。但是存在一定可能,导致结果误判。即元素不在集合中,查询结果却返回元素在集合中。

布隆过滤器一些的性质

  • 与哈希表不同,布隆过滤器是一个大小固定的过滤器,可以通过任意大的数字来描述集合大小
  • 添加一个元素到集合中永远不会添加失败,但误报率会随着添加元素数量的增多逐渐上升,直到集合中所有位都设置位1
  • 查询一个元素是否存在会产生误报的可能
  • 不应该从集合中删除元素。例如一个元素对应k的hash函数,当我们尝试删除,可能导致将hash值相同的元素也一并删除。

布隆过滤器的工作方式
一个空的布隆过滤器是一个由m个二进制位构成的数组。
在这里插入图片描述
我们需要k个hash函数来计算输入的hash值。当我们向过滤器中添加一个元素事,k个hash函数计算出的索引值 h1(x), h2(x),… hk(x)被设置位1。例如将geeks加入到过滤器中,我们用到3个hash函数,过滤器的长度为10,初始
值被设置为0。哈希函数的计算结果如下:

h1(“geeks”) % 10 = 1
h2(“geeks”) % 10 = 4
h3(“geeks”) % 10 = 7

接着我们将1,4,7位设置位1。
在这里插入图片描述
接着我们将nerd添加到集合中,hash值计算结果如下。

h1(“nerd”) % 10 = 3
h2(“nerd”) % 10 = 5
h3(“nerd”) % 10 = 4

在这里插入图片描述
如果我们想检查geeks是否在集合中,我们以相反的方式进行处理。我们使用h1,h2,h3计算初hash值。如果对应的二进制位都位1,那么可以判定“geeks”可能在集合中。如果任何一位为0,那么"geeks"一定不在集合中。

布隆过滤器结果误判
假如我们希望判定cat是否在集合中,首先计算hash值。得到1,3,7。但1,3,7是之前添加其它单词后设置的结果,我们之前并没有添加cat,因此造成了误判。

h1(“cat”) % 10 = 1
h2(“cat”) % 10 = 3
h3(“cat”) % 10 = 7

如果我们希望降低误判率,我们需要使用更多的hash函数及更大的数组。

布隆过滤器的误报概率
假设数组长度为m,并使用k个hash函数,n是要插入到过滤器中的元素个数,那么误报率的计算如下:
在这里插入图片描述
位数组的大小

如果过滤器中的元素数量已直,期望的误报率位p,那么二进制位数组大小计算公式如下:
在这里插入图片描述
最优哈希函数数量
如果m是数组长度,n是插入的元素个数,k是hash函数的个数,k计算公式如下:
在这里插入图片描述

哈希函数的选择
哈希函数独立且生成的数值均匀分布,并且尽可能的快。比如MurmurHash、Jenkins_hash_function。

2 Guava提供的布隆过滤器

首先添加依赖,版本可根据实际使用来调整。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>22.0</version>
</dependency>

创建布隆过滤器时要传入期望处理的元素数量,及最期望的误报的概率。如下分别是500和0.01。

BloomFilter<Integer> filter = BloomFilter.create(
  Funnels.integerFunnel(),
  500,
  0.01);

接着向过滤器中插入元素。

filter.put(1);
filter.put(2);
filter.put(3);

我们添加了3个元素,并且定义了最大元素数量为500,因此我们的过滤器将会产生非常准确的结果。我们使用mightContain()方法来测试。

assertThat(filter.mightContain(1)).isTrue();
assertThat(filter.mightContain(2)).isTrue();
assertThat(filter.mightContain(3)).isTrue();
 
assertThat(filter.mightContain(100)).isFalse();

因为布隆过滤器是一种概率型数据结构,因此返回true表示元素有极大的概率存在。当返回false那么表示元素一定不存在。

当我们创建布隆过滤器时,尽可能提供准确的元素数量。否则将会产生较高的误报率。

下面的例子表示集合最多5个元素,这样在实际使用时就会产生很高的误报率。

BloomFilter<Integer> filter = BloomFilter.create(
  Funnels.integerFunnel(),
  5,
  0.01);
 
IntStream.range(0, 100_000).forEach(filter::put);

3 参考资料

[1]布隆过滤器算法介绍,https://www.geeksforgeeks.org/bloom-filters-introduction-and-python-implementation/
[2]Guava中的布隆过滤器,https://www.baeldung.com/guava-bloom-filter

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Guava布隆过滤器是一种基于布隆过滤器算法的数据结构,用于高效地判断一个元素是否存在于一个大规模数据集中。它的主要特点是能够快速判断一个元素是否可能存在于集合中,同时能够有效地减少对底层存储的占用空间。 布隆过滤器采用位数组和多个哈希函数的组合方式来实现。当一个元素被插入到布隆过滤器中时,通过多个哈希函数对元素进行计算得到多个哈希值,并将对应的位数组位置标记为1。当判断一个元素是否存在时,同样通过多个哈希函数计算得到多个哈希值,然后检查对应的位数组位置是否都为1,若有一个位置不为1,则认为元素不存在。 Guava布隆过滤器提供了判断元素是否存在的方法以及其他一些相关的操作方法。它不支持删除元素,因为删除一个元素可能会影响到其他元素的判断结果。 Guava布隆过滤器在许多场景下都能发挥重要作用。它可以用于解决去重问题,例如在网络爬虫中过滤已经爬取过的URL,或者在大规模数据集中判断某个元素是否已存在。它也可以用于缓存或数据库查询等场景,用于快速判断某个数据是否可能存在,从而减轻对后端资源的压力。 然而,需要注意的是,Guava布隆过滤器在判断元素存在时可能会出现误判的情况。由于多个元素可能会映射到相同的位数组位置,且存在被多个元素标记为1的情况,因此在判断一个元素是否存在时,不能完全排除误判的可能性。 总而言之,Guava布隆过滤器是一种高效的数据结构,能够用于判断一个元素是否存在于一个大规模数据集中。它在去重、缓存等需求下发挥重要作用,但需要注意误判的可能性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值