布隆过滤器是集数据结构的一种 。 对于那些不了解的对象,“设置数据结构”仅包含一个主要方法。 它仅用于确定特定元素是否包含在一组元素中。 大多数数据结构(例如Hash Map , Linked List或Array )都可以相当轻松地创建此函数。 您只需要在数据结构中搜索特定元素。
但是,当集合中的元素数量超过可用内存量时,这些类型的数据结构可能会带来问题,因为这些类型的数据结构会将所有元素存储在内存中。
这是布隆过滤器变得有趣的地方。 因为布隆过滤器实际上并未将集合中的所有元素存储在内存中。
布隆过滤器没有将每个元素放入数据结构中,而是仅存储字节数组。 对于添加到布隆过滤器的每个元素,在其数组中设置k位。 这些位通常由哈希函数确定。
要检查元素是否在集合中,只需检查通常对于该项目通常为1的位是否实际上为1。 如果它们都是一(而不是零),则该项在集合内。 如果任何一位都不为1,则该项目不在集合内。
对于每个数据结构,肯定都会退回到Bloom Filter。 通过使用上述方法,布隆过滤器可以说元素实际上不在集合中。 假阳性在该集中是可能的,它们取决于几个因素,例如:
- 字节数组的大小
- 每个元素设置的位数(k)
- 集合中的项目数
通过调整上述值,您可以轻松地将误报概率提高到可观的水平,同时仍然节省大量空间。
发现布隆过滤器后,我开始寻找Java实现。 可悲的是,不存在标准实现! 因此,我编写了一个简单快速的Java版Bloom Filter版本。 您可以在GitHub上找到源代码 。
我的实现使用:
- MD5哈希
- 要添加一个Object,该集合采用hashCode()方法的值来计算MD5哈希。
- 由简单的字节数组支持
- 实现Set <Object>接口,尽管该接口中的某些方法将无法正常工作。
请注意,该项目还使用SizeOf库来获取内存中使用的字节数。
我还做了一些快速到期操作,以将过滤器与Java中的标准ArrayList进行比较,并进行了一些性能检查。
- 使用不同的k值将元素添加到集合中所需的时间
- 集合的大小与不同级别的数组列表
可以预期,集合中需要的元素数量越多,Bloom Filter变得越有用。 当确定布隆过滤器应该有多大以及给定集合的最佳k值时,确实会有些棘手,尤其是在集合不断增长的情况下。
对于测试,我仅向每个数据结构添加了对象(大小为16个字节),然后使用SizeOf库获取使用的真实空间量。
从上图可以很容易地看出,一旦数组变得大于100个对象,Bloom Filter的大小效率就会大大提高。 这种趋势持续到1500个对象,而布隆过滤器需要比ArrayList少22808字节来存储相同数量的元素。
上图显示了以秒为单位的时间(在2012年早期的iMac上),将元素添加到具有不同位数(k)的列表中的时间。 随着k的增加,时间会相当缓慢地增加到10位。 但是,任何超过10的东西都会变得非常昂贵,设置100位需要一整秒才能完成。
随时在GitHub上检查测试的源代码和Bloom Filter实现本身。
参考:来自我们的JCG合作伙伴 Isaac Taylor在Programming Mobile博客上的GitHub上的Java中Bloom过滤实现 。
翻译自: https://www.javacodegeeks.com/2012/11/bloom-filter-implementation-in-java-on-github.html