💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
在`Guava`的包中提供了布隆过滤器的实现,下面就让我们通过`Guava`提供的布隆过滤器来体会一下布隆过滤器的使用: 1. 还是使用之前的`redis-demo`项目,打开`pom.xml`文件,引入下面的`pom`依赖: ~~~java <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>29.0-jre</version> </dependency> ~~~ 在如下图所示位置引入: ![](https://img.kancloud.cn/44/25/4425cbc0a9f736c5d0a78405d4823bdc_822x379.png) 2. 在`src/main/java`目录下的`com.lonely.wolf.redis`包内新建一个测试类`GuavaBloomFilter.java`进行测试: ~~~java package com.lonely.wolf.redis; import com.google.common.base.Charsets; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class GuavaBloomFilter { private static final int expectedInsertions = 1000000; public static void main(String[] args) { BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8),expectedInsertions); List<String> list = new ArrayList<>(expectedInsertions); for (int i = 0; i < expectedInsertions; i++) { String uuid = UUID.randomUUID().toString(); bloomFilter.put(uuid); list.add(uuid); } int mightContainNum1 = 0; NumberFormat percentFormat =NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(2); //最大小数位数 for (int i=0;i < 500;i++){ String key = list.get(i); if (bloomFilter.mightContain(key)){ mightContainNum1++; } } System.out.println("【key真实存在的情况】布隆过滤器认为存在的key值数:" + mightContainNum1); System.out.println("-----------------------分割线---------------------------------"); int mightContainNum2 = 0; for (int i=0;i < expectedInsertions;i++){ String key = UUID.randomUUID().toString(); if (bloomFilter.mightContain(key)){ mightContainNum2++; } } System.out.println("【key不存在的情况】布隆过滤器认为存在的key值数:" + mightContainNum2); System.out.println("【key不存在的情况】布隆过滤器的误判率为:" + percentFormat.format((float)mightContainNum2 / expectedInsertions)); } } ~~~ 3. 同时,需要修改`pom.xml`文件中的`mainClass`属性,把这个类名修改正确: ~~~xml <mainClass>com.lonely.wolf.redis.GuavaBloomFilter</mainClass> ~~~ 4. 执行如下命令: ~~~bash # 进入主目录 cd /home/project/redis-demo # 将项目打包成一个 jar 包 mvn clean package -Dmaven.test.skip=true # 运行 java -jar target/redis-demo-1.0.0-SNAPSHOT.jar ~~~ 运行之后的结果为: ![](https://img.kancloud.cn/b1/19/b1195b771f798b12959c6f6ffd385a43_844x280.png) 第一部分输出的`mightContainNum1`一定是和`for`循环内的值相等,也就是百分百匹配。即满足了原则`1`:**如果元素实际存在,那么布隆过滤器一定会判断存在**。 第二部分的输出的误判率即`fpp`总是在`3%`左右,而且随着`for`循环的次数越大,越接近`3%`。即满足了原则`2`:**如果元素不存在,那么布隆过滤器可能会判断存在**。 这个`3%`的`fpp`是`Guava`中默认的`fpp`,且经过哈希计算次数默认为`5`次,这个`3%`的误判率和`5`次哈希运算需要多大空间位数组呢?这个大小可以[点击这里](https://hur.st/bloomfilter/?n=1000000&p=0.03&m=&k=)进行模拟计算,下图就是一个计算结果: ![](https://img.kancloud.cn/7a/00/7a00572e99168dbda9b97fd12a8a2a55_780x423.png) 得到的结果是`890kb`,`100W`的`key`才占用了`0.89M`,而如果是`10`亿呢,计算的结果是`870M`,这个内存空间是完全可以接受的。