Java实现布隆过滤器

一、概述

布隆过滤器本质上是一个很长的二进制数组,主要用来判断一个数据存不存在数组里,如果存在就用1表示,不存在用0表示,它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

二、实现原理

当一个元素被加入集合时,通过 K 个散列函数将这个元素映射成一个位数组中的 K 个点(offset),把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了,如果这些点有任何一个 0,则被检元素一定不在;如果都是 1,则被检元素很可能在。这就是布隆过滤器的基本思想。

布隆过滤器(Bloom Filter)是一个高空间利用率的概率性数据结构,由二进制向量(即位数组)和一系列随机映射函数(即哈希函数)两部分组成。

当布隆过滤器判定某个值存在时,其实这个值只是有可能存在;当它说某个值不存在时,那这个值肯定不存在,这个误判概率大约在 1% 左右。

1.布隆过滤器-添加元素

当使用布隆过滤器添加 key 时,会使用不同的 hash 函数对 key 存储的元素值进行哈希计算,从而会得到多个哈希值。根据哈希值计算出一个整数索引值,将该索引值与位数组长度做取余运算,最终得到一个位数组位置,并将该位置的值变为 1。每个 hash 函数都会计算出一个不同的位置,然后把数组中与之对应的位置变为 1。通过上述过程就完成了元素添加操作。

2.布隆过滤器-判定元素是否存在

当我们需要判断一个元素是否存时,首先对给定元素再次执行哈希计算,得到与添加元素时相同的位数组位置,判断所得位置是否都为 1,如果其中有一个为 0,那么说明元素不存在,若都为 1,则说明元素有可能存在。

三、布隆过滤器使用场景

1.解决Redis缓存穿透问题。

2.邮箱系统的垃圾邮件过滤功能也普遍用到了布隆过滤器,用了这个过滤器,平时也会遇到某些正常的邮件被放进了垃圾邮件目录中。

3.内容推荐,布隆过滤器能准确过滤掉那些已经看过的内容,没有看过的新内容,它也会过滤掉极小一部分 (误判),但是绝大多数新内容它都能准确识别。

四、布隆过滤器实现方式

1.引入Guava的依赖实现

csharp 复制代码
<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>32.0.1-jre</version>
</dependency>

2.代码实现如下:

csharp 复制代码
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterTest {
    public static void main(String[] args) {
        // 预期插入数量
        long capacity = 100000L;
        // 错误比率
        double errorRate = 0.001;
        //创建BloomFilter对象,需要传入Funnel对象,预估的元素个数,错误率
        BloomFilter<Long> filter = BloomFilter.create(Funnels.longFunnel(), capacity, errorRate);
        //put值进去
        for (long i = 0; i < capacity; i++) {
            filter.put(i);
        }
        // 统计误判次数
        int count = 0;
        // 我在数据范围之外的数据,测试相同量的数据,判断错误率是不是符合我们当时设定的错误率
        for (long i = capacity; i < capacity * 2; i++) {
            if (filter.mightContain(i)) {
                count++;
            }
        }
        System.out.println(count);
    }
}

结果为:假如数据为100000容错率为0.001,统计出来的误判个数是94。

因此,布隆过滤器容错还是非常可以的,当然也可以通过redis实现布隆过滤器,这里就不说明了。

相关推荐
uzong19 分钟前
程序员从大厂回重庆工作一年
java·后端·面试
kyle~23 分钟前
C++---value_type 解决泛型编程中的类型信息获取问题
java·开发语言·c++
开心香辣派小星4 小时前
23种设计模式-15解释器模式
java·设计模式·解释器模式
Halo_tjn5 小时前
虚拟机相关实验概述
java·开发语言·windows·计算机
摆烂z5 小时前
Docker与Jib(maven插件版)实战
java
RainbowSea5 小时前
从 Spring Boot 2.x 到 3.5.x + JDK21:一次完整的生产环境迁移实战
java·spring boot·后端
笨手笨脚の5 小时前
Spring Core常见错误及解决方案
java·后端·spring
奶油松果5 小时前
Springboot自动装配 - redis和redission
java·spring boot·redis
霍夫曼6 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
VX:Fegn08956 小时前
计算机毕业设计|基于Java人力资源管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端·课程设计