喝酒I创做I分享算法
生活中总有些东西值得分享数据结构
两周以前——ide
爬虫的原理就不细说了,无非是经过种子URL来顺藤摸瓜,爬取出网站关联的全部的子网页,存入本身的网页库当中。网站
可是,这其中涉及到一个小小的问题......spa
URL去重方案初版:HashSet3d
建立一个HashSet集合,把每个URL字符串做为HashSet的key插入到集合当中,利用HashSet的Key惟一性来对URL作去重。code
这个方案看似没毛病,可是通过几轮压测以后......
orm
每个URL按照20字节来算,一亿个URL就是20亿字节,也就是大约占了1.8G以上的空间。这么大的HashSet集合显然是不可取的。blog
因而小灰又思考了一番......内存
URL去重方案第二版:Bitmap
Bitmap是一种节省空间的数据结构,不太了解的朋友能够看看往期的相关文章:
具体怎么作呢?获取每个URL的HashCode,根据HashCode的值来插入到Bitmap的对应位置。若是要插入位置的值已是1,说明该URL已重复。
使用Bitmap之后,每个Url只占了1个Bit,一亿个Url占约12MB。假设整个Bitmap的空隙比较多,额外空间占90%,总空间也不过是120MB,相比HashSet来讲大大节省了内存空间。
这个方案貌似好了不少,但是......
String的Hashcode方法虽然尽量作到均匀分布,但仍然免不了会有冲突的状况。HashCode的冲突意味着什么呢?意味着两个本来并不相同的Url被误判为重复Url。
———————————————
听起来有点绕,咱们来详细描述一下:
1.把第一个URL按照三种Hash算法,分别生成三个不一样的Hash值。
2.把第二个URL也按照三种Hash算法,分别生成三个不一样的Hash值。
3.依次比较每个Hash结果,只有当所有结果都相等时,才断定两个URL相同。
具体怎样映射呢?流程以下:
1.建立一个空的Bitmap集合。
2.把第一个URL按照三种Hash算法,分别生成三个不一样的Hash值。
3.分别判断5,17, 9 在Bitmap的对应位置是否为1,只要不一样时为1,就认为该Url没有重复,因而把5,17,9的对应位置设置为1。
4.把第二个URL按照三种Hash算法,分别生成三个不一样的Hash值。
5.分别判断10,12, 9 在Bitmap的对应位置是否为1,只要不一样时为1,就认为该Url没有重复,因而把10,12, 9 的对应位置设置为1。
6.把第三个URL按照三种Hash算法,分别生成三个不一样的Hash值。
7.分别判断4,16, 11 在Bitmap的对应位置是否为1,只要不一样时为1,就认为该Url没有重复,因而把4,16, 11 的对应位置设置为1。
8.把第四个URL按照三种Hash算法,分别生成三个不一样的Hash值。
9.分别判断5,17, 9 在Bitmap的对应位置是否为1。判断的结果是 5,17, 9 在Bitmap对应位置的值都是1,因此断定该Url是一个重复的Url。
1.URL按照三个Hash算法获得三个结果。
2.分别判断10,12, 17 在Bitmap的对应位置是否为1。判断的结果是 10,12, 17 在Bitmap对应位置的值都是1,因此断定该Url是一个重复的Url。