日常生活中,包括在设计计算机软件时,我们经常要判断一个元素是否在一个集合中。比如在字处理软件中,需要检查一个英语单词是否拼写正确(也就是要判断它是否在已知的字典中);在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上;在网络爬虫里,一个网址是否被访问过等等。最直接的方法就是将集合中全部的元素存在计算机中,遇到一个新元素时,将它和集合中的元素直接比较即可。
一般来讲,计算机中的集合是用哈希表(hash table)来存储的。它的好处是快速准确,缺点是费存储空间。当集合比较小时,这个问题不显著,但是当集合巨大时,哈希表存储效率低的问题就显现出来了。
比如说,一个象 Yahoo,Hotmail 和 Gmai 那样的公众电子邮件(email)提供商,总是需要过滤来自发送垃圾邮件的人(spamer)的垃圾邮件。一个办法就是记录下那些发垃圾邮件的 email 地址。由于那些发送者不停地在注册新的地址,全世界少说也有几十亿个发垃圾邮件的地址,将他们都存起来则需要大量的网络服务器。
在如果用哈希表,每存储一亿个 email 地址, 就需要 1.6GB 的内存(用哈希表实现的具体办法是将每一个 email 地址对应成一个八字节的信息指纹,然后将这些信息指纹存入哈希表,由于哈希表的存储效率一般只有 50%,因此一个 email 地址需要占用十六个字节。一亿个地址大约要 1.6GB, 即十六亿字节的内存)。因此存贮几十亿个邮件地址可能需要上百 GB 的内存。除非是超级计算机,一般服务器是无法存储的。
今天,我们介绍一种称作布隆过滤器的数学工具,它只需要哈希表 1/8 到 1/4 的大小就能解决同样的问题。
布隆过滤器是由巴顿.布隆于一九七零年提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。我们通过上面的例子来说明起工作原理。
假定我们存储一亿个电子邮件地址,我们先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制位全部设置为零。对于每一个电子邮件地址 X,我们用八个不同的随机数产生器(F1,F2, ...,F8) 产生八个信息指纹(f1, f2, ..., f8)。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个自然数 g1, g2, ...,g8。现在我们把这八个位置的二进制位全部设置为一。当我们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。(见下图)
现在,让我们看看如何用布隆过滤器来检测一个可疑的电子邮件地址 Y 是否在黑名单中。我们用相同的八个随机数产生器(F1, F2, ..., F8)对这个地址产生八个信息指纹 s1,s2,...,s8,然后将这八个指纹对应到布隆过滤器的八个二进制位,分别是 t1,t2,...,t8。如果 Y 在黑名单中,显然,t1,t2,..,t8 对应的八个二进制一定是一。这样在遇到任何在黑名单中的电子邮件地址,我们都能准确地发现。
布隆过滤器决不会漏掉任何一个在黑名单中的可疑地址。但是,它有一条不足之处。也就是它有极小的可能将一个不在黑名单中的电子邮件地址判定为在黑名单中,因为有可能某个好的邮件地址正巧对应八个都被设置成一的二进制位。好在这种可能性很小。我们把它称为误识概率。在上面的例子中,误识概率在万分之一以下。
布隆过滤器的好处在于快速,省空间。但是有一定的误识别率。常见的补救办法是在建立一个小的白名单,存储那些可能别误判的邮件地址。
import java.util.BitSet;
public class SimpleBloomFilter {
private static final int DEFAULT_SIZE =2 << 24 ;
private static final int [] seeds =new int []{5,7, 11 , 13 , 31 , 37 , 61};
private BitSet bits= new BitSet(DEFAULT_SIZE);
private SimpleHash[] func=new SimpleHash[seeds.length];
public static void main(String[] args) {
String value = "stone2083@yahoo.cn" ;
SimpleBloomFilter filter=new SimpleBloomFilter();
System.out.println(filter.contains(value));
filter.add(value);
System.out.println(filter.contains(value));
}
public SimpleBloomFilter() {
for( int i= 0 ; i< seeds.length; i ++ ) {
func[i]=new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}
public void add(String value) {
for(SimpleHash f : func) {
bits.set(f.hash(value), true );
}
}
public boolean contains(String value) {
if(value ==null ) {
return false ;
}
boolean ret = true ;
for(SimpleHash f : func) {
ret=ret&& bits.get(f.hash(value));
}
return ret;
}
public static class SimpleHash {
private int cap;
private int seed;
public SimpleHash( int cap, int seed) {
this.cap= cap;
this.seed =seed;
}
public int hash(String value) {
int result=0 ;
int len= value.length();
for (int i= 0 ; i< len; i ++ ) {
result =seed* result + value.charAt(i);
}
return (cap - 1 ) & result;
}
}
}
运行:
C:\java>java SimpleBloomFilter
false
true
分享到:
相关推荐
自己写的Java抓图程序 原理见 http://blog.csdn.net/binyao02123202/archive/2010/07/12/5728840.aspx 用了序列化 线程 和BloomFilter算法
本篇文章将深入探讨Cuckoo Filter如何在某些情况下优于Bloom Filter,以及Go语言中实现Cuckoo Filter的细节。 首先,Bloom Filter是一种概率型数据结构,通过使用多个哈希函数将元素映射到位数组中。尽管它能高效地...
在提供的压缩包文件`Bloom Filter`中,可能包含了具体的Java实现代码,你可以通过阅读和分析这些代码来深入理解布隆过滤器的工作原理和Java实现细节。此外,还可以通过测试不同参数组合下的性能,进一步了解布隆过滤...
在这个Java实现的源码中,我们可以深入理解WM算法的工作原理及其在敏感词过滤中的应用。 WM算法的核心思想是通过建立一个模式库,将多个待匹配的模式(例如,敏感词)与待处理文本进行对比。每个模式都有一个权重值...
下面将详细介绍这三个算法及其在Java实现中的应用。 1. **Shingling(希尔链)** Shingling是一种将原始数据转化为更小的、可比较的表示方法。通常用于文本分析,特别是文档相似度计算。它首先将文本分割成单词...
解决方案 2:使用 Bloom filter,可以将一个文件中的 URL 映射到 340 亿 bit,然后检查另外一个文件中的 URL 是否与 Bloom filter 相匹配。 Scenario 2: 按照 query 的频度排序 在这个场景中,我们有 10 个文件,...
Apriori算法是一种经典的关联规则挖掘算法,...总之,Java实现Apriori算法需要理解其核心原理,设计合适的数据结构,并通过编程实现各个步骤。在实际应用中,还需要考虑性能优化和扩展性,以适应不同的数据规模和需求。
大数据处理算法目录中,主要介绍了三种大数据处理算法:Bitmap 算法、Bloom Filter 算法和分而治之/Hash 映射 + Hash 统计 + 堆/快速/归并排序。 大数据处理算法一:Bitmap 算法 Bitmap 算法是一种常用的大数据...
使用合适的数据结构和算法(如使用Trie或Bloom Filter优化查找)以及定期归档旧数据,可以提高统计效率。 10. **测试**:确保编写单元测试和集成测试来验证你的统计逻辑,特别是边界情况,如跨年、跨月的访问统计。...
Bloom Filter SHA-1 Message Digest Algorithm MD5 Base64 Graph data structure Strongly Connected Components(SCC) Prim's minimum spanning tree Kruskal MST Directed/Undirected graph ops Breadth First ...
总之,这个项目展示了如何利用Java实现高效的图像识别系统,特别是直方图比较算法在图像相似性检测中的优势。尽管基于哈希的图像指纹方法在某些方面可能更高效,但在这个特定案例中,直方图比较算法提供了更高的识别...
Bloom filter 是一种空间效率高、查询效率高的数据结构,可以用来实现数据字典、判重、集合求交集等操作。其原理是使用位数组+k 个独立的哈希函数,将哈希函数对应的值的位数组置 1,查找时如果发现所有哈希函数对应...
总结来说,Java实现文章汉字关键词(违禁词)识别需要结合多种数据结构和算法,如哈希表、Trie树、分词库和过滤算法。通过合理的设计和优化,我们可以构建出高效、准确的违禁词检测系统,满足内容审核的需求。
此外,为了优化性能,可能还会采用布隆过滤器(Bloom Filter)来减少不必要的计算,或者使用近似算法在牺牲一定精度的情况下提高查询速度。 标签中提到的“skyline_query”和“skyline_query_algorithm”指的是...
BF_MRSEClient-master 是本次课程设计的源代码文件,可能是使用某种编程语言(如Python或Java)实现的一个客户端程序,用于展示布隆过滤器(Bloom Filter)或其他某种特定算法的可视化过程。布隆过滤器是一种空间...
1. **BD**: 这可能指的是Bloom Filter(布隆过滤器),一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。它可能会有误报(将不存在的元素误认为存在),但不会漏报。 2. **ins_sort**: 这个...
4. **Java实现**: - 在Java中,可以使用数组或集合结构存储训练样本和其对应的类别信息。 - 距离计算可以通过自定义方法实现,如`calculateDistance()`。 - 选择K个最近邻时,可以使用优先队列(PriorityQueue)...
5. **优化策略**:为了提高效率,可以采用一些优化策略,如迭代过程中只传输离中心点较远的数据点,或者利用Bloom Filter减少不必要的计算。 在Java中实现MapReduce程序,主要涉及编写Mapper和Reducer类,以及Job...
五子棋游戏想必大家都非常熟悉,游戏规则十分简单。...Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes