让你彻底搞懂布隆过滤器!实现一个自己的BloomFilter
回顾上一节我们简单介绍了 BloomFilter 的原理 , 并且介绍了 guava BloomFilter 的使用 。
今天让我们更上一层楼 , 实现一个属于自己的 BoolFilter 。
文章插图
实现原理原理回顾布隆过滤器在本质上是二进制向量 。
在高层级上 , 布隆过滤器以下面的方式工作:
添加元素到过滤器 。
对元素进行几次哈希运算 , 当索引匹配哈希的结果时 , 将该位设置为 1 的 。
如果要检测元素是否属于集合 , 使用相同的哈希运算步骤 , 检查相应位的值是1还是0 。 这就是布隆过滤器明确元素不存在的过程 。 如果位未被设置 , 则元素绝不可能存在于集合中 。
当然 , 一个肯定的答案意味着 , 要不就是元素存在于集合中 , 要不就是遇见了哈希冲突 。
实现思路我们再加入一个元素时 , 通过多种不同的 hash 算法 , 然后设置到 bit 数组中 。
判断是否存在的时候 , 也对元素采用多种不同的 hash 算法 , 如果都为 true , 则说明可能存在 。 如果有不为 true 的 , 说明一定不不存在 。
文章插图
自己实现简单版本hash 算法可以参考 hash 算法介绍
- IHash.java
public interface IHash {/*** 根据 key 获取对应的hash值* @param key 字符串* @return hash 值*/int hashIndex(final String key);}
【让你彻底搞懂布隆过滤器!实现一个自己的BloomFilter】三个简单的实现:- HashOne
public class HashOne implements IHash {@Overridepublic int hashIndex(String key) {int hash = 0;for(int i = 0; i < key.length(); i++) {hash = 33 * hash + key.charAt(i);}return Math .abs(hash);}}
- HashTwo
public class HashTwo implements IHash {@Overridepublic int hashIndex(String key) {final int p = 16777619;int hash = (int) 2166136261L;for(int i = 0 ; i < key.length(); i++) {hash = (hash ^ key.charAt(i)) * p;}hash += hash << 13;hash ^= hash >> 7;hash += hash << 3;hash ^= hash >> 17;hash += hash << 5;return Math.abs(hash);}}
- HashThree
public class HashThree implements IHash {@Overridepublic int hashIndex(String key) {int hash, i;for (hash = 0, i = 0; i < key.length(); ++i) {hash += key.charAt(i);hash += (hash << 10);hash ^= (hash >> 6);}hash += (hash << 3);hash ^= (hash >> 11);hash += (hash << 15);return Math.abs(hash);}}
Bloom Fliter 实现- IBloomFilter.java
public interface IBloomFilter {/*** 添加一个元素* @param key元素*/void add(final String key);/*** 可能包含元素* @param key 元素* @return 可能包含*/boolean mightContains(final String key);}
- SimpleBloomFilter.java
import com.github.houbb.guava.learn.bloom.hash.HashOne;import com.github.houbb.guava.learn.bloom.hash.HashThree;import com.github.houbb.guava.learn.bloom.hash.HashTwo;public class SimpleBloomFilter implements IBloomFilter {private final int size;private boolean[] array;public SimpleBloomFilter(int size) {this.size = size;this.array = new boolean[size];}@Overridepublic void add(String key) {// 做三次 hashint hashOne = new HashOne().hashIndex(key);int hashTwo = new HashTwo().hashIndex(key);int hashThree = new HashThree().hashIndex(key);this.array[hashOne%array.length] = true;this.array[hashTwo%array.length] = true;this.array[hashThree%array.length] = true;}@Overridepublic boolean mightContains(String key) {// 做三次 hashint hashOne = new HashOne().hashIndex(key);int hashTwo = new HashTwo().hashIndex(key);int hashThree = new HashThree().hashIndex(key);if(!array[hashOne]) {return false;}if(!array[hashTwo]) {return false;}if(!array[hashThree]) {return false;}return true;}}
测试验证maven 引入com.github.houbb bloom-filter0.0.1
例子String text1 = "hello";String text2 = "world";BloomFilterBs bloomFilterBs = BloomFilterBs.newInstance().add(text1).add(text2);Assert.assertTrue(bloomFilterBs.mightContains(text1));Assert.assertFalse(bloomFilterBs.mightContains("other"));
性能问题当然我们实现版本的性能可能相对一般 , 可以参考下 guava 的实现 。后续我们有时间可以阅读下 guava BoolmFilter 的源码 。
小结本节回顾了 Bloom Filter 的实现思路 , 并且通过 java 实现了属于我们自己的布隆过滤器 。
工作中就算不使用自己造的轮子 , 知其然知其所以然 , 有问题自己也知道大概的排查方向 。
目前的版本非常的简陋 , 还有很多可以改进的地方 , 我们后续可以阅读下 guava 的源码 , 并化为己用 。
布隆过滤器使用也不存在需要注意的点 , 下一节我们来讲一讲使用的最佳实践 。
- 荣耀V30|麒麟990+40W快充,昔日猛将彻底沦为清仓价?网友:太遗憾
- 美国|印度宣布彻底突破5G难关,美英加澳一片欢呼,一周后白宫怒斥被骗
- 涡轮|看法米特涡轮流量计如何让你得心应手
- 大战|一亿像素平民化,Redmi掀起千元机大战,卢伟冰彻底让友商绝望!
- 小米10纪念至尊版|小米彻底疯狂!米10至尊只卖4690!米粉不约吗?
- 设置页面|QQ突然更新,加入了一项新功能,可以让你创建一个独一无二的QQID
- 流畅|手机里垃圾太多,关闭这个开关,彻底清除垃圾,手机立刻流畅
- 内容|怎样才能让你的小程序留住更多用户
- 隐私安全|华为怎样让你的隐私只属于你?
- 海淘|收到海淘包裹如何降低病毒感染风险?专家回应:手要彻底清洗