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实现布隆过滤器,这里就不说明了。

相关推荐
kill bert2 小时前
Java八股文背诵 第四天JVM
java·开发语言·jvm
你是理想5 小时前
wait 和notify ,notifyAll,sleep
java·开发语言·jvm
helloworld工程师5 小时前
【微服务】SpringBoot整合LangChain4j 操作AI大模型实战详解
java·eclipse·tomcat·maven
Java&Develop5 小时前
idea里面不能运行 node 命令 cmd 里面可以运行咋回事啊
java·ide·intellij-idea
q567315236 小时前
使用Java的HttpClient实现文件下载器
java·开发语言·爬虫·scrapy
你们补药再卷啦6 小时前
不用额外下载jar包,idea快速查看使用的组件源码
java·ide·intellij-idea
爱的叹息6 小时前
Spring Boot 自定义配置类(包含字符串、数字、布尔、小数、集合、映射、嵌套对象)实现步骤及示例
java·linux·spring boot
@西瓜@7 小时前
JAVAEE(多线程-线程池)
java·开发语言
returnShitBoy8 小时前
Go语言中的垃圾回收是如何工作的?
java·jvm·golang
有什么东东8 小时前
山东大学软件学院创新项目实训开发日志(9)之测试前后端连接
java