大数据处理算法二:Bloom Filter算法

百度面试题:给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法。通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合。

 

一. 实例 

  为了说明Bloom Filter存在的重要意义,举一个实例:

   (实例一),假设要你写一个网络蜘蛛(web crawler)。由于网络间的链接错综复杂,蜘蛛在网络间爬行很可能会形成“环”。为了避免形成“环”,就需要知道蜘蛛已经访问过那些URL。给一个URL,怎样知道蜘蛛是否已经访问过呢?稍微想想,

         (实例二)给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

就会有如下几种方案:

  1. 将访问过的URL保存到数据库。

  2. 用HashSet将访问过的URL保存起来。那只需接近O(1)的代价就可以查到一个URL是否被访问过了。

  3. URL经过MD5或SHA-1等单向哈希后再保存到HashSet或数据库。

  4. Bit-Map方法。建立一个BitSet,将每个URL经过一个哈希函数映射到某一位。

  方法1~3都是将访问过的URL完整保存,方法4则只标记URL的一个映射位。

       以上方法在数据量较小的情况下都能完美解决问题,但是当数据量变得非常庞大时问题就来了。

  方法1的缺点:数据量变得非常庞大后关系型数据库查询的效率会变得很低。而且每来一个URL就启动一次数据库查询是不是太小题大做了?

  方法2的缺点:太消耗内存。随着URL的增多,占用的内存会越来越多。就算只有1亿个URL,每个URL只算50个字符,就需要5GB内存。

  方法3:由于字符串经过MD5处理后的信息摘要长度只有128Bit,SHA-1处理后也只有160Bit,因此方法3比方法2节省了好几倍的内存。

  方法4消耗内存是相对较少的,但缺点是单一哈希函数发生冲突的概率太高。还记得数据结构课上学过的Hash表冲突的各种解决方法么?若要降低冲突发生的概率到1%,就要将BitSet的长度设置为URL个数的100倍。

 

  实质上上面的算法都忽略了一个重要的隐含条件:允许小概率的出错,不一定要100%准确!也就是说少量url实际上没有没网络蜘蛛访问,而将它们错判为已访问的代价是很小的——大不了少抓几个网页呗。 

例如有 一组字符 arr:”哈哈“,”呵呵“........

字符串:“哈哈”

哈希算法1处理后:8

哈希算法2处理后:1

哈希算法1处理后:3

插入BitArray后

再处理字符串:“呵呵”

哈希算法1处理后:2

哈希算法2处理后:1

哈希算法1处理后:9

继续插入BitArray后,如果继续游字符串,继续以这种方式插入

判断”在这些字符串是否包含”嘻嘻“

哈希算法1处理后:0

哈希算法2处理后:1

哈希算法1处理后:7

只要判断 下标分别为 0,1,7位置的值是否都为1,如下图 因为位置0跟位置7的值不为1

所以”嘻嘻“不包含在arr中,反之如果都为1怎包含

java代码实现如下

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

/**
 * BloomFilter算法
 *
 * @author JYC506
 *
 */
public class BloomFilter {
    /*哈希函数*/
	private List<IHashFunction> hashFuctionList;
    /*构造方法*/
	public BloomFilter() {
		this.hashFuctionList = new ArrayList<IHashFunction>();
	}
    /*添加哈希函数类*/
	public void addHashFunction(IHashFunction hashFunction) {
		this.hashFuctionList.add(hashFunction);
	}
    /*删除hash函数*/
	public void removeHashFunction(IHashFunction hashFunction) {
		this.hashFuctionList.remove(hashFunction);
	}
    /*判断是否被包含*/
	public boolean contain(BitSet bitSet, String str) {
		for (IHashFunction hash : hashFuctionList) {
			int hashCode = hash.toHashCode(str);
			if(hashCode<0){
				hashCode=-hashCode;
			}
			if (bitSet.get(hashCode) == false) {
				return false;
			}
		}
		return true;
	}
    /*添加到bitSet*/
	public void toBitSet(BitSet bitSet, String str) {
		for (IHashFunction hash : hashFuctionList) {
			int hashCode = hash.toHashCode(str);
			if(hashCode<0){
				hashCode=-hashCode;
			}
			bitSet.set(hashCode, true);
		}
	}

	public static void main(String[] args) {
		BloomFilter bloomFilter=new BloomFilter();
		/*添加3个哈希函数*/
		bloomFilter.addHashFunction(new JavaHash());
		bloomFilter.addHashFunction(new RSHash());
		bloomFilter.addHashFunction(new SDBMHash());
		/*长度为2的24次方*/
		BitSet bitSet=new BitSet(1<<25);
		/*判断test1很test2重复的字符串*/
		String[] test1=new String[]{"哈哈","我","大家","逗比","有钱人性","小米","Iphone","helloWorld"};
		for (String str1 : test1) {
			bloomFilter.toBitSet(bitSet, str1);
		}
		String[] test2=new String[]{"哈哈","我的","大家","逗比","有钱的人性","小米","Iphone6s","helloWorld"};
		for (String str2 : test2) {
			if(bloomFilter.contain(bitSet, str2)){
				System.out.println("'"+str2+"'是重复的");
			}
		}
		System.out.println(new RSHash().toHashCode("哈哈"));
		System.out.println(new RSHash().toHashCode("aa"));
	}
}
/*哈希函数接口*/
interface IHashFunction {
	int toHashCode(String str);
}

class JavaHash implements IHashFunction {

	@Override
	public int toHashCode(String str) {
		return str.hashCode();
	}

}

class RSHash implements IHashFunction {

	@Override
	public int toHashCode(String str) {
		int b = 378551;
		int a = 63689;
		int hash = 0;
		for (int i = 0; i < str.length(); i++) {
			hash = hash * a + str.charAt(i);
			a = a * b;
		}
		return hash;
	}

}

class SDBMHash implements IHashFunction {

	@Override
	public int toHashCode(String str) {
		int hash = 0;
		for (int i = 0; i < str.length(); i++)
			hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;
		return hash;
	}

}

时间: 2024-08-26 19:54:01

大数据处理算法二:Bloom Filter算法的相关文章

Bloom Filter 算法详解

Bloom Filter 算法 Bloom filter是由Burton Bloom 在1970年提出的,其后在P2P上得到了广泛的应用.Bloom filter 算法可用来查询某一数据是否在某一数据集合中.其优点是查询效率高.可节省空间,但其缺点是会存在一定的错误.因此Bloom filter 算法只能应用于那些允许有一定错误的场合.可使用Bloom filter 算法的场合包括字典软件.分布式缓存.P2P网络和资源路由等等. 使用Bloom Filter我们可以判断一个元素是否在某一个集合中

Bloom Filter 算法具体解释

Bloom Filter 算法 Bloom filter是由Burton Bloom 在1970年提出的,其后在P2P上得到了广泛的应用.Bloom filter 算法可用来查询某一数据是否在某一数据集合中.其长处是查询效率高.可节省空间.但其缺点是会存在一定的错误.因此Bloom filter 算法仅仅能应用于那些同意有一定错误的场合.可使用Bloom filter 算法的场合包含字典软件.分布式缓存.P2P网络和资源路由等等. 使用Bloom Filter我们能够推断一个元素是否在某一个集合

海量数据处理算法之Bloom Filter

算法介绍 Bloom Filter的中文名称叫做布隆过滤器,因为他最早的提出者叫做布隆(Bloom),因而而得此名.布隆过滤器简单的说就是为了检索一个元素是否存在于某个集合当中,以此实现数据的过滤.也许你会想,这还不简单,判断元素是否存在某集合中,遍历集合,一个个去比较不就能得出结果,当然这没有任何的问题,但是当你面对的是海量数据的时候,在空间和时间上的代价是非常恐怖的,显然需要更好的办法来解决这个问题,而Bloom Filter就是一个不错的算法.具体怎么实现,接着往下看. Bloom Fil

利用bloom filter算法处理大规模数据过滤

Bloom Filter是由Bloom在1970年提出的一种快速查找算法,通过多个hash算法来共同判断某个元素是否在某个集合内.可以用于网络爬虫的url重复过滤.垃圾邮件的过滤等等. 它相比hash容器的一个优势就是,不需要存储元素的实际数据到容器中去来一个个的比较是否存在. 只需要对应的位段来标记是否存在就行了,所以想当节省内存,特别适合海量的数据处理.并且由于省去了存储元素和比较操作,所以性能也比基于hash容器的高了很多. 但是由于bloom filter没有去比较元素,只通过多个has

Bloom Filter算法

<?php /*Bloom Filter算法来去重过滤. 介绍下Bloom Filter的基本处理思路:申请一批空间用于保存0 1信息,再根据一批哈希函数确定元素对应的位置,如果每个哈希函数对应位置的值为全部1,说明此元素存在.相反,如果为0,则要把对应位置的值设置为1.由于不同的元素可能会有相同的哈希值,即同一个位置有可能保存了多个元素的信息,从而导致存在一定的误判率. 如果申请空间太小,随着元素的增多,1会越来越多,各个元素冲突的机会越来越来大,导致误判率会越来越大.另外哈希函数的选择及个数

Bloom Filter 算法简介 (增加 Counting Bloom Filter 内容)

Bloom Filter的中文翻译叫做布隆过滤器,是1970年由布隆提出的.它实际上是一个很长的二进制向量和一系列随机映射函数.布隆过滤器可以用于检索一个元素是否在一个集合中.它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难.如文章标题所述,本文只是做简单介绍,属于科普文章. 应用场景在正式介绍Bloom Filter算法之前,先来看看什么时候需要用到Bloom Filter算法.1. HTTP缓存服务器.Web爬虫等主要工作是判断一条URL是否在现有的URL集

大数据处理算法一:Bitmap算法

腾讯面试题:给20亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中并且所耗内存尽可能的少? 解析:bitmap算法就好办多了 所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况.通常是用来判断某个数据存不存在的. 例如,要判断一千万个人的状态,每个人只有两种状态:男人,女人,可以用0,1表示.那么就可以开一个int数组,一个int有32个位,就可以表示32个人.操作的时候可以使用位操作. 一,

数组的常用算法二之排序算法

冒泡排序冒泡排序从小到大排列 public class TestArray { public static void main(String[] args){ //冒泡排序从小到大排列 int[] a=new int[]{54,78,4,87,75}; for (int i=0;i<a.length-1;i++){ for (int j=0;j<a.length-1-i;j++){ if (a[j]>a[j+1]){ int temp=a[j]; a[j]=a[j+1]; a[j+1]=

【转】海量数据处理算法-Bloom Filter

1. Bloom-Filter算法简介 Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在于集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合.而在能容忍低错误率的应用场合下,Bloom Fi