谷歌的数学之美系列曾经提到过一种数据结构叫做bloomfilter,翻译成中文就是布隆过滤,文中使用布隆过滤器来过滤黑名单。后来我在毕业设计中也用到了它来过滤重复的URL,避免网络爬虫重复抓取。再后来在单位又一次的用到了bloomfilter来过滤用户的重复访问。随着海量数据时代的到来,布隆过滤器应用的场景越来越多。
布隆过滤器(Bloom Filter)是1970年由Burton Howard Bloom提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
初始状态时,Bloom Filter是一个包含m位的位数组,每一位都置为0。
为了表达S={X1, X2,…,Xn}这样一个n个元素的集合,Bloom Filter使用k个相互独立的哈希函数(Hash Function),它们分别将集合中的每个元素映射到{1,…,m}的范围中。对任意一个元素X,第i个哈希函数映射的位置Hi(X)就会被置为1(1≤i≤k)。注意,如果一个位置多次被置为1,那么只有第一次会起作用,后面几次将没有任何效果。在下图中,k=3,且有两个哈希函数选中同一个位置(从左边数第五位)。
在判断Y是否属于这个集合时,我们对Y应用k次哈希函数,如果所有Hi(Y)的位置都是1(1≤i≤k),那么我们就认为Y是集合中的元素,否则就认为Y不是集合中的元素。下图中Y1就不是集合中的元素。Y2或者属于这个集合,或者刚好是一个误判。
应用布隆过滤器时,只需要由用户决定要容纳的元素数n和希望的误判率p。然后通过以下公式:
计算出位数组的长度m,然后通过m,n计算出哈希函数的个数k。
布隆过滤器的优劣主要与哈希函数的质量相关,而且哈希函数之间的相关度越小越好,每个哈希函数本身的计算过程不要太复杂,不然会影响效率。理想情况下是取k个完全不相关的哈希函数,在不是很严格情况下,也可以通过一个哈希函数的参数变化产生k个不同的哈希函数,比如将i(1≤i≤k)作为参数参与哈希函数的计算。
不同的应用场景,哈希函数的设计方法不同,没有通用的规律可循。在网络爬虫的设计中,我才用了MD5算法最为基础来构造哈希函数:
for (int i = 0; i < funNum; i++){
//输入URL地址拼接上Hash函数的编号
String input = url+i.toString();
//散列值取MD5摘要的后64位与比特向量大小的的余数
hash =(long)Md5(input).getLast64bit() % (long)bitSetSize;
}
在过滤用户时,由于用户ID是一个long型数据,因此用随机数函数random()效率更高。下面是long类型bloomfilter的完整实现。
import java.io.Serializable;
import java.util.BitSet;
import java.util.Random;
/**
* Long类型元素的布隆过滤器
*/
public class BloomFilter implements Serializable {
private static final long serialVersionUID = 1L;
public static final int ELEM_NUM = 1000; // 欲容纳的元素个数
public static final double PERCENTAGE = 0.001; // 希望的误差率
private int hashNum; // hash函数的数量
private int size; // 位向量的長度
private BitSet bitVecter; // 位向量
public BloomFilter() {
size = (int) Math.abs(ELEM_NUM * Math.log(PERCENTAGE)
/ (Math.log(2) * Math.log(2))) + 1;
hashNum = (int) (Math.log(2) * ((double) size / ELEM_NUM));
bitVecter = new BitSet(size);
}
/**
* 查找元素是否在集合中
*/
public boolean search(Long elem) {
boolean flag = true;
int temp;
Random random = new Random(elem);
for (int i = 0; i < hashNum; i++) {
temp = random.nextInt(size);
if (!bitVecter.get(temp)) {// 元素不在集合中
bitVecter.set(temp);
flag = false;
}
}
return flag;
}
/**
* 获取位向量的长度
*/
public int size() {
return bitVecter.size();
}
public int getHashNum() {
return hashNum;
}
public void setHashNum(int hashNum) {
this.hashNum = hashNum;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public BitSet getBitVecter() {
return bitVecter;
}
public void setBitVecter(BitSet bitVecter) {
this.bitVecter = bitVecter;
}
}
- 大小: 3.5 KB
- 大小: 5.7 KB
- 大小: 5 KB
- 大小: 1.4 KB
- 大小: 739 Bytes
分享到:
相关推荐
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。由布隆在1970年提出,它不像传统的数据结构如哈希表那样保证不误判,而是允许有一定的错误率。这种特性使得...
布隆过滤器是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。它是由 Burton Howard Bloom 在1970年提出的,主要应用于大数据存储和检索,尤其在数据库、缓存系统和网络搜索等领域有广泛...
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。在Java开发中,特别是在处理大数据、内存限制或需要快速查询是否存在某个元素的场景下,布隆过滤器是一个...
例如,`bf_create(size_t capacity, uint8_t num_hashes)`用于创建一个布隆过滤器,`bf_insert(bloom_filter* filter, const void* item)`用于插入元素,`bf_query(bloom_filter* filter, const void* item)`用于...
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。它可能会误判,但不会漏判,即如果它说一个元素在集合中,那可能是错误的,但如果它说一个元素不在集合中,那么...
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。在大数据处理、缓存系统、分布式存储等领域有着广泛的应用。这个压缩包文件“bloom filter布隆过滤器学习...
布隆过滤器,大家学过数据结构的应该都清楚,一般的字典树要实现嵌入和查找都内存的消耗非常大,布隆过滤器有BloomFilter,string, BKDRHash, APHash, DJBHash> bf五个参数你要查找的元素个数,查找元素类型,三个...
- `Intersection(other *BloomFilter)`: 计算两个布隆过滤器的交集,创建一个新的布隆过滤器,只保留同时存在于两个过滤器中的元素的位。 4. **优化策略**: - **位数组大小**:位数组的大小直接影响误判率,需要...
布隆过滤器是一种高效的空间节省的数据结构,用于判断一个元素是否可能在一个集合中,但可能会产生一定的误判率。它由一个很长的二进制向量和多个独立的哈希函数组成。布隆过滤器的基本原理是,当一个元素被添加到...
Redis集成布隆过滤器需要使用Redis 4.0以上版本,或者使用Redis 6.x版本,使用官方提供的插件机制或编译安装RedisBloom模块。使用布隆过滤器可以解决大量数据去重问题,提高系统性能和效率。 布隆过滤器的优点是: ...
`bloomfilter.js`可能是JavaScript版本的布隆过滤器实现,而"Go-布隆过滤器的一个Go实现参考bloomfilter.js"则表明该Go版本的实现是借鉴了JavaScript版本的设计思路或代码结构。 Go实现布隆过滤器的关键组件包括: ...
在PHP和Redis中实现布隆过滤器,可以利用PHP的扩展库,如BloomFilter库,或者直接在Redis中使用BF.ADD、BF.MEMBERS和BF.EXISTS等命令操作布隆过滤器。Redis的布隆过滤器模块提供了方便的操作接口,能够在分布式环境...
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。在C++中实现布隆过滤器,可以有效地处理大量数据,尤其是在内存有限的情况下。这个压缩包文件"Bloom_filter...
C++实现的布隆过滤器,其中使用到的bitset也是自己简单实现的一个BitContainer。可以处理千万条到亿条记录的存在性判断。做成dll可以在很多场合使用,如自己写爬虫,要判断一个url是否已经访问过,判断一个单词是否...
【布隆过滤器(Bloom Filter)的Java实现】 布隆过滤器是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。它可能会产生误报(false positive),但不会产生漏报(false negative)。在Java...
在Python中,有多个库实现了布隆过滤器,其中一个就是我们这里提到的"python-bloomfilter-master"。 这个Python库提供了对布隆过滤器的简单接口,使得开发者可以方便地在项目中应用布隆过滤器。安装过程非常直观,...
布隆过滤器是一种数据结构,主要用于判断一个元素是否可能在一个集合中存在。它可以在插入和查询数据时快速地判断一个元素是否可能在这个集合中,比如在缓存中查询一个元素是否存在。 它的原理是使用多个哈希函数对...
**布隆过滤器(Bloom Filter)**是一种空间效率极高的概率型数据结构,用于测试一个元素是否在一个集合中。由Burton Howard Bloom在1970年提出,主要用于节省存储空间,尤其在大数据场景下,它能有效地解决大规模...
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。它可能会误判,但不会漏判,即可能存在假阳性(False Positive),但绝不会有假阴性(False Negative)。...