日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?

發(fā)布時(shí)間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何快速判断某 URL 是否在 20 亿的网址 URL 集合中? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

假設(shè)遇到這樣一個(gè)問(wèn)題:一個(gè)網(wǎng)站有 20 億 url 存在一個(gè)黑名單中,這個(gè)黑名單要怎么存?若此時(shí)隨便輸入一個(gè) url,你如何快速判斷該 url 是否在這個(gè)黑名單中?并且需在給定內(nèi)存空間(比如:500M)內(nèi)快速判斷出

可能很多人首先想到的會(huì)是使用?HashSet,因?yàn)?HashSet基于?HashMap,理論上時(shí)間復(fù)雜度為:O(1)。達(dá)到了快速的目的,但是空間復(fù)雜度呢?URL字符串通過(guò)Hash得到一個(gè)Integer的值,Integer占4個(gè)字節(jié),那20億個(gè)URL理論上需要:20億*4/1024/1024/1024=7.45G的內(nèi)存,不滿足空間復(fù)雜度的要求。

這里就引出本文要介紹的“布隆過(guò)濾器”。

何為布隆過(guò)濾器

百科上對(duì)布隆過(guò)濾器的介紹是這樣的:

布隆過(guò)濾器(Bloom Filter)是1970年由布隆提出的。它實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù)。布隆過(guò)濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中。它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間都比一般的算法要好的多,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。

是不是描述的比較抽象?那就直接了解其原理吧!

還是以上面的例子為例:

哈希算法得出的Integer的哈希值最大為:Integer.MAX_VALUE=2147483647,意思就是任何一個(gè)URL的哈希都會(huì)在0~2147483647之間。

那么可以定義一個(gè)2147483647長(zhǎng)度的byte數(shù)組,用來(lái)存儲(chǔ)集合所有可能的值。為了存儲(chǔ)這個(gè)byte數(shù)組,系統(tǒng)只需要:2147483647/8/1024/1024=256M。

比如:某個(gè)URL(X)的哈希是2,那么落到這個(gè)byte數(shù)組在第二位上就是1,這個(gè)byte數(shù)組將是:000….00000010,重復(fù)的,將這20億個(gè)數(shù)全部哈希并落到byte數(shù)組中。

判斷邏輯:

如果byte數(shù)組上的第二位是1,那么這個(gè)URL(X)可能存在。為什么是可能?因?yàn)橛锌赡芷渌黆RL因哈希碰撞哈希出來(lái)的也是2,這就是誤判。

但是如果這個(gè)byte數(shù)組上的第二位是0,那么這個(gè)URL(X)就一定不存在集合中。

多次哈希:

為了減少因哈希碰撞導(dǎo)致的誤判概率,可以對(duì)這個(gè)URL(X)用不同的哈希算法進(jìn)行N次哈希,得出N個(gè)哈希值,落到這個(gè)byte數(shù)組上,如果這N個(gè)位置沒(méi)有都為1,那么這個(gè)URL(X)就一定不存在集合中。

Guava的BloomFilter

Guava框架提供了布隆過(guò)濾器的具體實(shí)現(xiàn):BloomFilter,使得開(kāi)發(fā)不用再自己寫一套算法的實(shí)現(xiàn)。

創(chuàng)建BloomFilter

BloomFilter提供了幾個(gè)重載的靜態(tài)?create方法來(lái)創(chuàng)建實(shí)例:

public?static?<T>?BloomFilter<T>?create(Funnel<??super?T>?funnel,?int?expectedInsertions,?double?fpp); public?static?<T>?BloomFilter<T>?create(Funnel<??super?T>?funnel,?long?expectedInsertions,?double?fpp); public?static?<T>?BloomFilter<T>?create(Funnel<??super?T>?funnel,?int?expectedInsertions); public?static?<T>?BloomFilter<T>?create(Funnel<??super?T>?funnel,?long?expectedInsertions);

最終還是調(diào)用:

static?<T>?BloomFilter<T>?create(Funnel<??super?T>?funnel,?long?expectedInsertions,?double?fpp,?Strategy?strategy); //?參數(shù)含義: // funnel 指定布隆過(guò)濾器中存的是什么類型的數(shù)據(jù),有:IntegerFunnel,LongFunnel,StringCharsetFunnel。 //?expectedInsertions?預(yù)期需要存儲(chǔ)的數(shù)據(jù)量 // fpp 誤判率,默認(rèn)是0.03。

BloomFilter里byte數(shù)組的空間大小由?expectedInsertions,?fpp參數(shù)決定,見(jiàn)方法:

static?long?optimalNumOfBits(long?n,?double?p)?{if?(p?==?0)?{p?=?Double.MIN_VALUE;}return?(long)?(-n?*?Math.log(p)?/?(Math.log(2)?*?Math.log(2))); }

真正的byte數(shù)組維護(hù)在類:BitArray中。

使用:

最后通過(guò):put和?mightContain方法,添加元素和判斷元素是否存在。

算法特點(diǎn)

1、因使用哈希判斷,時(shí)間效率很高。空間效率也是其一大優(yōu)勢(shì)。2、有誤判的可能,需針對(duì)具體場(chǎng)景使用。3、因?yàn)闊o(wú)法分辨哈希碰撞,所以不是很好做刪除操作。

使用場(chǎng)景

1、黑名單 2、URL去重 3、單詞拼寫檢查 4、Key-Value緩存系統(tǒng)的Key校驗(yàn) 5、ID校驗(yàn),比如訂單系統(tǒng)查詢某個(gè)訂單ID是否存在,如果不存在就直接返回。

總結(jié)

以上是生活随笔為你收集整理的如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。