布隆过滤器 原理及优缺点分析_布隆过滤器误判怎么办

布隆过滤器 原理及优缺点分析_布隆过滤器误判怎么办用于检索一个元素是否在集合中,其空间和时间上及其优秀!

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

布隆过滤器

今天我们来聊一聊布隆过滤器,了解他之前,我们先看一看是干什么用的

img

百度百科解释他可以判断一个元素是否在集合中,后面还说了他的效率呀什么的都很好,那既然如此,我们再想象一下为什么需要它!

img

针对上述问题,如果我们直接任由请求访问数据库,问题1、2 还行,如果是问题3,那数据库大抵要说栓Q了。既然如此,我们结合刚刚看到的 布隆过滤器 正好是用来判断一个元素是否存在集合中。而且它的优点就是 空间效率、查询时间都比别人要好的多。那不得看看他到底是咋好的撒。

别急!先骗一波关注!骗不到也没事,咱也不小心眼,接着往下说;

img

如何实现高效率的判断一个元素在不在集合中呢!有的小伙伴立刻就联想到了 List.contains() 方法。如果光靠这个方法,在数据量较大的情况,还是会存在效率问题

img

根据源码我们可以看到他是挨个遍历的,意味每次都要遍历全量的集合。那既然每次都要遍历整个集合,那有什么办法呢?

把集合长度变短!对!布隆过滤器就是这样干的,那元素怎么放呢?

我们可以把任意一个需要比较的元素,通过函数,生成2个或3个甚至更多个整数。道理大致和 hash 差不多,只不过这里是生成多个整数

我们假如二进制向量的长度为9,散列函数的个数为3的布隆过滤器,针对元素X,三个不同的散列函数分别生成的哈希值为1,4,8。则上图转变为:

img

同理,我们再存一个元素Y,如果散列函数返回 4,6,9 的话,图变为:

img

假设,我们要判断元素Z,此时通过计算哈希返回 1,4,5 的话,发现其中 5 为 0,就可以判断 元素 Z 不存在此容器中。

由此我们可以客观的判断出其优缺点:

优点:

  1. 空间占用极小,因为本身不存储数据而是用比特位表示数据是否存在,某种程度有保密的效果。
  2. 插入与查询时间复杂度均为 O(k),常数级别,k 表示散列函数执行次数
  3. 散列函数之间可以相互独立,可以在硬件指令层加速计算。

缺点:

  1. 误差(假存在性)
  2. 无法删除

布隆过滤器可以 100% 的判断元素不在集合中,但是当集合元素非常多都为1时,此时散列函数凑巧又生成了存在的值,就可以判断为 假性存在(假阳性)

如何解决误差问题

在创建布隆过滤器时我们为了找到合适的 m 和 k ,可以根据预期元素数量 n 与 ε 来推导出最合适的 m 与 k

  • 位数组长度 m
  • 散列函数个数 k
  • 预期元素数量 n
  • 期望误差 ε

img

img

算法实现:

// 计算哈希次数
@VisibleForTesting
static int optimalNumOfHashFunctions(long n, long m) {
    // (m / n) * log(2), but avoid truncation due to division!
    return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
}
 
// 计算位数组长度
@VisibleForTesting
static long optimalNumOfBits(long n, double p) {
    if (p == 0) {
        p = Double.MIN_VALUE;
    }
    return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
}

这样我们就可以科学的确定数组长度、散列个数。

我们来看下一个问题

无法删除!

布隆过滤器判断一个元素存在就是判断对应位置是否为1来确定的,但是如果要删除掉一个元素是不能直接把1改成0的,因为这个位置可能存在其它元素,所以如果要支持删除,那我们应该怎么做呢?

最简单的做法就是加一个计数器,就是说位数组的每个位如果不存在就是0,存在几个元素就存具体的数字,而不仅仅只是存1。那么这就有一个问题,本来存1就是一位就可以满足了,但是如果要存具体的数字比如说2,那就需要2位了,所以带有计数器的布隆过滤器会占用更大的空间

参考资料:

布隆过滤器如何删除

布隆过滤器原理实现

百度百科

最后给点个关注吧 img

关注 『Xiang想』公众号

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185062.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • LARGE_INTEGER类型和QueryPerformanceFrequency()「建议收藏」

    LARGE_INTEGER类型和QueryPerformanceFrequency()「建议收藏」LARGE_INTEGER类型和QueryPerformanceFrequency()LARGE_INTEGERLARGE_INTEGER是union,用于表示一个64位有符号整数值,其他定义如下:Typedefunion_LARGE_INTEGER{Struct{ DWORD  LowPart;    LONG    HighPart;    };LO…

    2022年7月16日
    9
  • SpringCloud微服务架构分析

    SpringCloud微服务架构分析微服务框架微服务是一种架构风格,一个大型复杂软件应用应该由一个或多个微服务组成。系统中的各个微服务都可以被独立部署,每个服务仅关注于完成一件任务就行了,在所有情况下,每个任务都代表着一个小的业务能力。微服务架构其实就是一种架构风格,我们将整个项目划分为多个独立的小项目,也就是我们俗称的微服务,可以理解为每个微服务都单独处理某个功能模块,可以独立开发、测试、部署、监控和扩展,甚至可以用不同的编程语言开发它们。它有利于我们平时项目的开发,解决了一体化架构项目难以扩展,开发周期长,故障级联等问题…

    2022年6月15日
    31
  • PHP UEditor富文本编辑器 显示 后端配置项没有正常加载,上传插件不能正常使用…

    PHP UEditor富文本编辑器 显示 后端配置项没有正常加载,上传插件不能正常使用…

    2021年10月11日
    302
  • oracle数据库定义变量和使用_oracle执行变量

    oracle数据库定义变量和使用_oracle执行变量一、异常错误介绍我们在使用oracle数据库做程序开发时,一般都会使用plsql做客户端连接查询工具,在写sql语句时plsql经常会报并非所有变量都已绑定01008这样类似的异常错误,通常我们程序员还看不出具体有什么毛病,具体错误提示见下图显示:出现以上这种错误出现的次数多了,我们就会有经验解决了,经过我们常年的工作经验以及网友的问题汇总,得出的最终结论就是:程序员sql语句书写不严谨导致该问题…

    2022年9月7日
    0
  • mybatis的rowbounds是物理分页吗_rowbounds分页

    mybatis的rowbounds是物理分页吗_rowbounds分页mybatis中,使用RowBounds分页,非常方便不需要在sql语句中写limit,mybatis会自动拼接sql,添加limit最核心的是在mapper接口层,传参时传入RowBounds(intoffset,intlimit)对象,即可完成分页注意:由于java允许的最大整数为2147483647,所以limit能使用的最大整数也是…

    2022年9月22日
    0
  • idea搭建vue(使用VUE打开一个项目)

    使用IDEA创建咱们的第一个VUE项目最近在学习VUE,想着使用vscode、hbulider、webstorm这些软件学习,但听前端前辈们说要很多插件什么的等等等!听完咱还是选择IDEA吧,毕竟和IDEA还是很亲近的!1.安装环境–让VUE‘顺产’(1)安装node.js至于为什么安装大家可以看看前辈们的博客哦!1.先让IDAE准备准备(迎接VUE)~~~提示:这里可以添加要学的内容例如:1、搭建Java开发环境2、掌握Java基本语法3、掌握条件语句4、掌握循环

    2022年4月14日
    296

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号