<转载>最简单理解位图BitMap和布隆过滤器BloomFilter

一切的数据结构和算法都是为了解决问题,而不是面试! -- 鲁迅

先不要前戏,直接给结论

  • BitMap:把数值转化为数组的下标,下标对应的值只存放一个bit 0或1 ,0不存在 1存在。判断时 根据数值当做下标找到对应的 bit 值,1存在,0不存在
  • BloomFilter:把内容通过多个hash算法,转换成多个数组下标,下标对应的值只存放一个bit 0或1 ,0不存在 1存在。判断过滤时 多个下标对应的值都为1,则可能存在,只要有一个值为0,则一定不存在

先看两个面试题

  • 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中【腾讯】
  • 给40亿个不重复的邮箱,没排过序。给一个邮箱,如何快速判断这个邮箱是否在这40亿个邮箱中,允许误判

暂停几分钟,好好思考一下。大佬的话请跳过~

思路

问题一

  1. 不用考虑放在一个List里遍历了,放不下的!一个int数占4个字节,40亿个数毛估下来是16G

既然这样不行的原因是使用到的内存太大,那么聪明的你可能想怎么解决内存过大的问题

  • 一种常见的想法就是干脆不用内存存储,我把所有的数放到文件里,我读文件判断!只是磁盘I/O 的速度对比参考下表,完全不满足题目中快速的定义
  • 一台机器不行,我多开几台总可以吧,开个16台,一台机器只需要1G内存就可以了,机智如你!但是有俩致命问题:第一资源占用量问题,第二如果面试官让你当场写一个多机协作通讯的代码咋办~
  1. 其实题目已经暴露了参考答案~ 没错第一个问题可以采用 位图法 解决

举个栗子:
十以内的 7 个数( 1,2,3,4,5,7,0 )中,快速查找一个数 ( 6 )是否存在?
新建一个bit数组,他的容量就是十,默认每个 bit 值为 0 意思为十个位置的数都不存在:
bit[] arr = {0,0,0,0,0,0,0,0,0,0}

把 7 个数初始化进数组,把值当做坐标

  • 初始化 1 --> {0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
  • 初始化 2 --> {0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
  • 初始化 3 --> {0, 1, 1, 1, 0, 0, 0, 0, 0, 0}
  • 初始化 4 --> {0, 1, 1, 1, 1, 0, 0, 0, 0, 0}
  • 初始化 5 --> {0, 1, 1, 1, 1, 1, 0, 0, 0, 0}
  • 初始化 7 --> {0, 1, 1, 1, 1, 1, 0, 1, 0, 0}
  • 初始化 0 --> {1, 1, 1, 1, 1, 1, 0, 1, 0, 0}

最终结果:
bit[] arr = {1,1,1,1,1,1,0,1,0,0}

查找 6 是否存在即是看数组下标是 6 的值是多少:arr[6] = 0 所以数字 6 不存在!

现在是十以内的7个数,效果还看不出来,但是如果你用这个思想考虑第一道面试题呢?

优缺点就不说了,自己悟吧,很简单。

问题二

你可能发现了,bitmap 处理数字很方便,但是处理字符就稍微有点困难了 解决方法就是 布隆过滤器(BloomFilter)

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

举个栗子:
现在有两个 Hash 算法,都可以把邮箱地址转换成10以内的数字,现在有两个邮箱 a@javasoso.com b@javasoso.com,需要查询 c@javasoso.com 是否存在
同样的,新建一个容量为十的 bit 数组,默认每个 bit 值为0,表示当前下标的值不存在
bit[] arr = {0,0,0,0,0,0,0,0,0,0}

把所有的邮箱初始化进数组中:

a@javasoso.com
- hash 算法一 计算出值为 1 --> {0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
- hash 算法二 计算出值为 5 --> {0, 1, 0, 0, 0, 1, 0, 0, 0, 0}
b@javasoso.com
- hash 算法一 计算出值为 3 --> {0, 1, 0, 1, 0, 1, 0, 0, 0, 0}
- hash 算法二 计算出值为 9 --> {0, 1, 0, 1, 0, 1, 0, 0, 0, 1}

最终结果:
bit[] arr = {0, 1, 0, 1, 0, 1, 0, 0, 0, 1}

查询 c@javasoso.com
- hash 算法一 计算出值为 9 arr[9] = 1 第一个hash值存在,需要查看第二个hash算法计算值
- hash 算法二 计算出值为 4 arr[4] = 0 第二个hash值不存在,只要有一个hash值不存在,这个邮箱肯定不存在
- 假如 hash 算法二 计算出值为 1,arr[1] = 1 也是存在的,只能证明 c@javasoso.com 可能存在

应该看出来了吧,其实它是位图法的进阶版,也很好理解。只是有一定的误差率,但是效率是杠杠的!在大数据过滤中应用比较多

如果你还没看懂,可以提一下你的疑问点,我继续完善。

 

 


标题:最简单理解位图BitMap和布隆过滤器BloomFilter
作者:zsr251
地址:https://www.javasoso.com/articles/2019/11/16/1573894776568.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值