【Java|布隆过滤器】本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构,特点是高效地插入和查询,用来告诉我们“某样东西一定不存在或者可能存在”。相比于传统的 List、Set、Map等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。拥有极高的性能,无论写入操作还是读取操作,时间复杂度是O(1)。
- 用途
- 解决Redis缓存穿透
- 在爬虫时,对爬虫网址进行过滤,已经存在布隆中的网址,不在爬取。
- 垃圾邮件过滤,对每一个发送邮件的地址进行判断是否在布隆的黑名单中,如果在就判断为垃圾邮件。
- 原理
- 特性
- 一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在。
- 布隆过滤器可以添加元素,但是不能删除元素。因为删掉元素会导致误判率增加。
- 优缺点
- 优点:优点很明显,二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。
- 缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据
- 为何存在误判?误判率是多少?如何减小误判?
为何相同的bit位被多次映射为1,因为映射函数本身就是散列函数,散列函数是会有碰撞的。
布隆过滤器的默认误算率大概为3%。
布隆过滤器有一个可预测的误判率(FPP):
文章图片
- n 是已经添加元素的数量;
- k 哈希的次数;
- m 布隆过滤器的长度(如比特数组的大小);
- 选择多个 Hash 函数计算多个 hash 值,可以减少误判
- m/n越大,hash次数越多,误判率越低。
Bloom Filter Calculator(输入预期元素数量和可接受的误判率,可看到最佳配置)
- 哈希碰撞
2、为何会有hash碰撞?
由于通过哈希函数产生的哈希值是有限的,而要哈希的数据是无穷的,导致经过哈希函数处理后仍然有不同的数据对应相同的值。这时候就产生了哈希冲突。一般情况下,哈希值越长的哈希算法,散列冲突的概率越低。
3、Hash碰撞解决方案
- 开放寻址法(再散列法):当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。(线性探测再散列、二次探测再散列、伪随机探测再散列)
- 再哈希法(Rehash):同时构造多个不同的哈希函数,当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
- 链地址法(拉链法):基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。【HashMap的哈希冲突解决方法】
推荐阅读
- 深度学习|TensorFlow惊现大bug(网友(这是逼着我们用PyTorch啊!))
- java|IT界惊现文豪!华为领导及阿里P10遭吐槽
- java|突发!Spring Cloud 爆高危漏洞。。赶紧修复!!
- Java URLConnection类
- Java URL
- 了解javap工具
- Java try-catch块
- Java抛出关键字(throw和throws)
- Java抛出异常(throw关键字:throw关键字)