布隆过滤器讲解及基于Guava BloomFilter案例

目录

1、布隆过滤器是什么

2、主要作用

3、存储过程

4、查询过程

5、布隆过滤器的删除操作

6、优点

7、缺点

8、测试误判案例

8.1、引入Guava依赖

8.2、编写测试代码

8.3、测试

8.4、BloomFilter实现原理

 9、总结


推荐博主视频,讲的很棒:布隆过滤器详解

1、布隆过滤器是什么

        布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制(0和1组成的)向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

  • 布隆过滤器里面就是一个二进制(存储0和1)的数组,下标从0开始

2、主要作用

  • 通过一个的hash函数,计算出数据的hash值,再把哈希值映射到数组中
  • 判断这个数据是不是存储在这个数组中,不存在则返回0,存在则返回1,其实就是用二进制(0和1)去表示数据是否存在这个数组中

3、存储过程


已下面案例为例:

步骤:

  1. 布隆过滤器在没有存储任何数据时,默认都是0
  2. 布隆过滤器中有3个哈希(Hash)函数(这3个哈希函数一定是互不影响的),现在传入一个"你好"的值,通过这3个哈希函数,算出对应的哈希值
  3. Hash1函数通过计算得到哈希值,对应数组中下标为3的位置,从而把数据映射至index=3处
  4. 布隆过滤器会把下标为3的二进制向量改为1
  5. 同理,经过其他2个哈希函数,分别存储在下标为5、7的位置,并把0改为1 

4、查询过程

还是以上面的案例为例:

步骤:

  1. 布隆过滤器会根据传入的值,通过3个哈希函数计算出该值存储的下标
  2. 判断该下标是否为1,为1则表示该下标存储了该值,为0则表示没有存储
  3. 由于上述布隆过滤器有3个哈希函数,因此判断该值存不存在,必须满足得到的3个下标的二进制向量值等于1,才能证明该值存在于该数组中,布隆过滤器返回1,只要有一个等于1,则认为该数值中不存在该值,布隆过滤器返回0.

5、布隆过滤器的删除操作

  • 在布隆过滤器中,很难进行删除操作,如下:

 现在有2个值:

  • 你好
  • hello
  1. 假设上述的2个值在经过Hash函数计算时,得到了相同的hash值(hash冲突),这时他们都存储在下标index=2的位置
  2. 之后,我们需要在布隆过滤器中,移除值"你好"的数据,经过Hash函数计算出该值存储在下标为2的位置
  3. 然后布隆过滤器会把该值删除,并把下标为2的二进值向量改为0
  4. 这时,当我们在查询"hello"是否存在时,布隆过滤器会得到0,认为不存在
  5. 也就是意味着,当多个值存储在同一处下标时,删除任意1个值,其他的值也会被删除
  6. 由于布隆过滤器会造成误删,因此布隆过滤器很难做删除操作

6、优点

  • 由于布隆过滤器是由二进制数组组成的数据,所占用的空间很小
  • 插入和查询的速度快:布隆过滤器会经过hash函数,计算出哈希值,再映射至数组的下标即可;时间复杂度为O(K),K=hash函数的个数
  • 数据的保密性好,因为数组中存储的不是原始数据,而是0和1的二进制数据

7、缺点

  • 很难进行删除操作
  • 会对数据是否存在,进行误判:由于判断数据的hash值是可能相同的(hash冲突),对把不存在的数据的hash值,计算出于数组中已存储的哈希值相同,得到结果为1,从而造成误判

注意:误判是无法避免的,我们只能减少误判的概率

8、测试误判案例

8.1、引入Guava依赖

  • Guava工具包是由Google提供的,里面封装了布隆过滤器,直接使用即可
<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>31.1-jre</version>
</dependency>

8.2、编写测试代码

使用到布隆过滤器的代码都在注释中进行说明了:

package com.shuizhu.test;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author 睡竹
 * @date 2023/4/8
 * 布隆过滤器误判率测试案例
 */
public class BloomFilterTest {

    //日志,用于执行记录时间
    private static final Log log = LogFactory.getLog(BloomFilterTest.class);
    
    //模拟布隆过滤器预计存储数据的大小,这里设置为100万
    private static int size = 1000000;
    //设置 期望的误判率
    private static double error = 0.000000000001;
    /**
     *  创建布隆过滤器
     *  Integer:表示过滤器存储的是整数类型的数据
     *  Funnels.integerFunnel():表示过滤器只对整数类型进行判断
     */
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, error);
    //设置样本数据为100万
    private static int total = 1000000;

    public static void main(String[] args) {
        //1、在布隆过滤器中,插入样本数据
        for (int i = 0; i < total; i++) {
            //使用put()插入即可
            bloomFilter.put(i);
        }
        //2、定义一个误判数据量的计量值
        int count = 0;
        //3、误判测试前,打印下一句话,用于测试误判测试时间
        log.warn("误判开始");
        /**
         * 4、添加10万个布隆过滤器中不存在的数据,用于测试误判率
         *
         *    这里直接在total的基础上,再加10万的数据
         */
        for (int i = total; i < total+100000; i++) {
            //mightContain()判断数据是否存在于布隆过滤器中
            if (bloomFilter.mightContain(i)) {
                count++;
                //System.out.println("数据:" + i + "误判了");
            }
        }
        log.warn("误判结束");
        //打印误判数据及耗时
        System.out.println("总共误判数为:" + count);
    }
}

8.3、测试

<1>在误判率为0.01下,执行结果为:

 

  • 在12ms内执行完成
  • 误判数为:947(测试总数为10万)
  • 真实误判率为:947 ÷ 10万 = 0.00947 0.01 ,符合预期

<2>修改误判率为0.03:

  

执行结果如下:

 

  • 在16ms内执行完成
  • 误判数为:3033
  • 真实误判率也与预期的0.03相近

总结:设置的误判率是能直接影响布隆过滤器最终的误判率的,误判率越低,耗时越多

问题:我们是不是把误判率设置为无限小,那么就不存在误判了呢?


<3>修改误判率为0.0000000001

 

该误判率比之前2个案例数值小很多,我们看下执行效果:

 

  • 在25ms内执行完成
  • 误判数为0 

注意:在测试机器上是特别快的,当在高并发下,误判率越小,耗时越多,会给服务器带来性能损耗。

因此:我们需要根据具体的业务需求,设置合理的误判率


8.4、BloomFilter实现原理

以8.3中的案例:

1>在误判率为0.01下,我们debug下:

debug启动:

 2>在误判率为0.03下,我们继续debug下:

3>在误判率为0.0000000001下,我们继续debug下: 

 9、总结

  • 误差率需要根据具体的业务需求进行设置
  • 误差率越小,所占用的空间就越大,需要的哈希函数也就越多

原因:

  1. 因为在一个hash函数下,只有一个函数对数据进行计算,hash值重复概率会很大,当多个hash函数计算同一个数据时,由于每个hash函数是相互隔离的(hash算法不同),因此重复的概率也随之减少。
  2. hash函数越多,计算出的hash值也就越多,hash值越多,对应的二进制数据也就越多,所有占用的空间也就越大

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10057.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为运动健康服务Health Kit 6.10.0版本新增功能速览!

华为运动健康服务&#xff08;HUAWEI Health Kit&#xff09;6.10.0 版本新增的能力有哪些&#xff1f; 阅读本文寻找答案&#xff0c;一起加入运动健康服务生态大家庭&#xff01; 一、 支持三方应用查询用户测量的连续血糖数据 符合申请Health Kit服务中开发者申请资质要求…

大数据项目之电商数据仓库系统回顾

文章目录一、实训课题二、实训目的三、操作环境四、 实训过程&#xff08;实训内容及主要模块&#xff09;五、实训中用到的课程知识点六、实训中遇到的问题及解决方法七、课程实训体会与心得八、程序清单一、实训课题 大数据项目之电商数据仓库系统 二、实训目的 完成一个电…

7.基于概率距离快速削减法的风光场景生成与削减方法

matlab代码&#xff1a;基于概率距离快速削减法的风光场景生成与削减方法 采用蒙特卡洛进行场景生成&#xff0c;并再次进行场景缩减。 clear;clc; %风电出力预测均值E W[5.8,6.7,5.8,5.1,6.3,5,6.2,6,4.1,6,7,6.8,6.5,6.9,5,5.6,6,5.8,6.2,4.7,3.3,4.4,5.6,5]; %取标准差为风…

在unreal中的基于波叠加的波浪水面材质原理和制作

关于水的渲染模型 如何渲染出真实的水体和模拟&#xff0c;是图形学&#xff0c;游戏开发乃至仿真领域很有意思的一件事 记得小时候玩《Command & Conquer: Red Alert 3》&#xff0c;被当时的水面效果深深震撼&#xff0c;作为一款2008年出的游戏&#xff0c;现在想起它…

算法:将一个数组旋转k步

题目 输入一个数组如 [1,2,3,4,5,6,7]&#xff0c;输出旋转 k 步后的数组。 旋转 1 步&#xff1a;就是把尾部的 7 放在数组头部前面&#xff0c;也就是 [7,1,2,3,4,5,6]旋转 2 步&#xff1a;就是把尾部的 6 放在数组头部前面&#xff0c;也就是 [6,7,1,2,3,4,5]… 思路 思…

C++继承(上)

一、继承的概念及定义1.继承的概念2.继承定义2.1定义格式2.2继承关系和访问限定符2.3继承基类成员访问方式的变化二、基类和派生类对象赋值转换三、继承中的作用域一、继承的概念及定义 1.继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允…

聊聊如何运用JAVA注解处理器(APT)

什么是APT APT&#xff08;Annotation Processing Tool&#xff09;它是Java编译期注解处理器&#xff0c;它可以让开发人员在编译期对注解进行处理&#xff0c;通过APT可以获取到注解和被注解对象的相关信息&#xff0c;并根据这些信息在编译期按我们的需求生成java代码模板或…

【SQL Server】数据库开发指南(一)数据库设计

文章目录一、数据库设计的必要性二、什么是数据库设计三、数据库设计的重要性五、数据模型5.1 实体-关系&#xff08;E-R&#xff09;数据模型5.2 实体&#xff08;Entity&#xff09;5.3 属性&#xff08;Attribute&#xff09;5.5 关系&#xff08;Relationship&#xff09;六…

和ChatGPT-4聊完后,我觉得一切可能已经来不及了

了然无味&#xff0c;晴空万里&#xff01;和ChatGPT-4开始了一场坦诚的沟通&#xff0c;它全程都表现出高情商&#xff0c;以及不断尽量安抚我的情绪&#xff0c;而这&#xff0c;恰恰令我脊背发凉。 部分文字截取 ZM&#xff1a;我能不能理解每次对话就是一次你的“生命” G&…

LeetCode刷题6:二叉树篇之第 1 节

提示1&#xff1a;本篇先带大家了解二叉树的基础理论&#xff0c;后给出4道基础题目&#xff0c;不难&#xff0c;冲啊~ 算法刷题系列 LeetCode刷题1&#xff1a;数组篇LeetCode刷题2&#xff1a;链表篇LeetCode刷题3&#xff1a;哈希篇LeetCode刷题4&#xff1a;字符串篇Lee…

1678_计算机架构黄金时代_文章阅读

全部学习汇总&#xff1a; GreyZhang/g_risc_v: Learning notes about RISC V. (github.com) 看了一份几年前的文章&#xff0c;觉得还是挺有收获的&#xff0c;因此做一个简单的整理。 对于架构有很大影响的主要考虑四点&#xff1a;专用硬件的实现、高安全性的要求、开放指令…

【Pandas】① Pandas 数据处理基础

介绍 Pandas 是非常著名的开源数据处理库&#xff0c;我们可以通过它完成对数据集进行快速读取、转换、过滤、分析等一系列操作。除此之外&#xff0c;Pandas 拥有强大的缺失数据处理与数据透视功能&#xff0c;可谓是数据预处理中的必备利器。 知识点 数据类型数据读取数据选择…

有效的括号(力扣刷题)代码随想录刷题

给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类型的左…

RK3568平台开发系列讲解(驱动基础篇)mmap系统调用详解

🚀返回专栏总目录 文章目录 一、什么是mmap二、mmap映射类型2.1、私有匿名映射2.2、私有文件映射2.3、共享文件映射2.4、共享匿名映射沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文将详细介绍mmap系统调用。 一、什么是mmap mmap/munmap函数是用户空间中常用的…

Nacos 性能报告

目录 一、测试目的 二、测试工具 三、测试环境 1. 环境 服务端 客户端 2. 启动参数 服务端 客户端 四、测试场景 1. 大规模服务注册后达到稳定状态 场景描述 2. 大规模服务注册达到稳定状态后&#xff0c;部分实例频繁发布 场景描述 五、测试数据 1. 大规模服务…

软件测试基础

软件测试的定义、软件测试的目的 IEEE&#xff1a;The process of running or testing the system manually or automatically by using tools, in order to verify whether it satisfies the requirements or to make clear the differences between the actual outcome and…

DDoS攻击实验笔记

DoS&DDoS简介 DoS(Denial of Service)&#xff0c;拒绝服务攻击是通过一些方法影响服务的可用性&#xff0c;比如早期主要基于系统和应用程序的漏洞&#xff0c;只需要几个请求或数据包就能导致长时间的服务不可用&#xff0c;但易被入侵检测系统发现。 DDoS(Distributed D…

日撸 Java 三百行day28-30

文章目录说明day28-30 Huffman 编码 (节点定义与文件读取)1.建树过程&#xff08;以图为例&#xff09;2.哈夫曼树特点3.分析代码过程3.1 抽象成员变量3.2结合文章梳理思路1.读文本2.解析文本内容&#xff1a;3.建树4.生成哈夫曼编码5.编码6.解码4.其他4.1 java 类型强转4.2 ja…

linux线程调度策略

系统中既有分时调度&#xff0c;又有时间片轮转调度和先进先出调度 学习这个主要为了在linux多线程中&#xff0c;解决几条指令间延时在1-2ms内&#xff1b; 1.比如之前处理过&#xff1a;给一个板子发送一个can指令&#xff0c;接着需要给另外一个模块发送移动指令&#xff0c…

用ChatGPT怎么赚钱?普通人用这5个方法也能赚到生活费

ChatGPT在互联网火得一塌糊涂&#xff0c;因为它可以帮很多人解决问题。比如&#xff1a;帮编辑人员写文章&#xff0c;还可以替代程序员写代码&#xff0c;帮策划人员写文案策划等等。ChatGPT这么厉害&#xff0c;能否用它来赚钱呢&#xff1f;今天和大家分享用ChatGPT赚钱的5…