最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java利用布隆過濾器實(shí)現(xiàn)快速檢查元素是否存在

 更新時(shí)間:2022年10月24日 08:55:10   作者:指北君  
布隆過濾器是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù)。布隆過濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中。本文就來詳細(xì)說說實(shí)現(xiàn)的方法,需要的可以參考一下

Guava BloomFilter

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

基本概念

當(dāng)需要判斷某個(gè)元素是否在某個(gè)數(shù)據(jù)集中時(shí),一般會(huì)怎么做?

  • 將數(shù)據(jù)集封裝成集合,比如List、Set等
  • 通過集合提供的API判斷該元素是否存在于集合

這樣的實(shí)現(xiàn)比較簡(jiǎn)單,同時(shí)通過現(xiàn)有的JDK都能很快達(dá)到目的,但是設(shè)想一下,如果上面說到的集合數(shù)據(jù)量非常的大,這樣不僅會(huì)耗費(fèi)較大的存儲(chǔ)空間,同時(shí) 在集合中檢索元素的時(shí)間復(fù)雜度也會(huì)隨之增加。那么有沒比較好的方法去實(shí)現(xiàn)判斷元素是否存在這樣的情形呢?

也就是布隆過濾器

通過一系列的Hash函數(shù)將元素映射到一個(gè)位陣列(Bit Array)中的多個(gè)點(diǎn)位上,判斷元素是否存在,則是判斷所有點(diǎn)位是不是都為1。然而,位陣列上都為1并不一定能夠保證該元素一定存在,也有可能是其他元素Hash后落在了該點(diǎn)位上,這就是布隆過濾器的誤判。

因此通過布隆過濾器我們可以確定:

  • 元素可能在集合中
  • 元素一定不在集合中

應(yīng)用場(chǎng)景

網(wǎng)頁(yè)爬蟲時(shí)忽略已經(jīng)判定的URL路徑

郵箱通過設(shè)置過濾垃圾郵件

集合重復(fù)元素的判別,有效判斷元素不在集合中

防止數(shù)據(jù)緩存時(shí)的緩存穿透問題

優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 相比于其它的數(shù)據(jù)結(jié)構(gòu),布隆過濾器在空間和時(shí)間方面都有巨大的優(yōu)勢(shì)。
  • 布隆過濾器存儲(chǔ)空間和插入/查詢時(shí)間都是常數(shù)。
  • Hash函數(shù)相互之間沒有關(guān)系,方便由硬件并行實(shí)現(xiàn)。
  • 布隆過濾器不需要存儲(chǔ)元素本身,對(duì)保密要求非常嚴(yán)格的場(chǎng)合有優(yōu)勢(shì)。
  • 布隆過濾器可以表示全集,其它任何數(shù)據(jù)結(jié)構(gòu)都不能。

缺點(diǎn)

  • 元素存在的誤判
  • 一般情況下不支持元素(位陣列)的刪除

實(shí)現(xiàn)原理

核心其實(shí)是元素如何存儲(chǔ)?如何判斷元素是否存在?核心方法就兩個(gè),一個(gè)“存”一個(gè)檢查,里面涉及到了算法相關(guān)知識(shí),感興趣可以深入研究下其實(shí)現(xiàn)原理與思想。

put 將元素放入過濾器中,但不是存儲(chǔ)

????????public?<T>?boolean?put(@ParametricNullness?T?object,?Funnel<??super?T>?funnel,?int?numHashFunctions,?LockFreeBitArray?bits)?{
????????????long?bitSize?=?bits.bitSize();?//?位數(shù)組,可以通過redis來實(shí)現(xiàn)分布式的布隆過濾器
????????????long?hash64?=?Hashing.murmur3_128().hashObject(object,?funnel).asLong();?//通過funnel將對(duì)象轉(zhuǎn)換成基本類型并計(jì)算64位hash
????????????int?hash1?=?(int)hash64;?//?取低32位
????????????int?hash2?=?(int)(hash64?>>>?32);?//?取高32位
????????????boolean?bitsChanged?=?false;
????????????//?
????????????for(int?i?=?1;?i?<=?numHashFunctions;?++i)?{
????????????????int?combinedHash?=?hash1?+?i?*?hash2;
????????????????if?(combinedHash?<?0)?{
????????????????????combinedHash?=?~combinedHash;
????????????????}

????????????????bitsChanged?|=?bits.set((long)combinedHash?%?bitSize);
????????????}

????????????return?bitsChanged;
????????}

mightContain 與put相似,計(jì)算的過程相同,不同的是值的判斷

????????public?<T>?boolean?mightContain(@ParametricNullness?T?object,?Funnel<??super?T>?funnel,?int?numHashFunctions,?LockFreeBitArray?bits)?{
????????????long?bitSize?=?bits.bitSize();
????????????long?hash64?=?Hashing.murmur3_128().hashObject(object,?funnel).asLong();
????????????int?hash1?=?(int)hash64;
????????????int?hash2?=?(int)(hash64?>>>?32);

????????????for(int?i?=?1;?i?<=?numHashFunctions;?++i)?{
????????????????int?combinedHash?=?hash1?+?i?*?hash2;
????????????????if?(combinedHash?<?0)?{
????????????????????combinedHash?=?~combinedHash;
????????????????}

????????????????if?(!bits.get((long)combinedHash?%?bitSize))?{
????????????????????return?false;
????????????????}
????????????}

????????????return?true;
????????}

我們可以簡(jiǎn)單第理解其實(shí)現(xiàn)原理?比如現(xiàn)在有一個(gè)容器,我們定義為String[] bitArray = new String[26]作為位陣列, 現(xiàn)在有一堆由小寫英文組成的元素,我們假定Hash算法為a-z到1~26的映射。

  • 現(xiàn)在有一個(gè)元素abc,hash后為1110000000...,保存到bitArray :1110000000...
  • 現(xiàn)在有一個(gè)元素cde, hash后為0011100000...,保存到bitArray :1111100000...
  • 現(xiàn)在又有一個(gè)新的元素ade,hash后同樣為100110000...,很明顯會(huì)認(rèn)為該元素存在,這就是FFP

為什么判斷元素一定不在集合中呢?很顯然,如果一個(gè)元素存在,則該元素hash后的bit數(shù)組必須全部都是1,反之則不存在

示例

????@Test
????public?void?match(){
????????BloomFilter?filter?=?BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()),10000,0.2);
????????List<String>?ids?=?new?ArrayList<>();

????????IntStream.rangeClosed(1,10000).forEach(index->{
????????????String?id?=?UUID.randomUUID().toString();
????????????ids.add(id);
????????????filter.put(?id?);
????????});

????????ids.forEach(id->{
????????????//?正常情況下全部失敗,但是會(huì)有?20%的返回true
????????????System.out.println(?id?+?":"?+?filter.mightContain(?id+1?));
????????});
????}

流程很簡(jiǎn)單:

  • 根據(jù)配置構(gòu)建BloomFilter對(duì)象
  • 通過put方法,初始化數(shù)據(jù)到filter
  • 通過方法mightContain判斷元素是否存在

結(jié)束語(yǔ)

BloomFilter雖然看起來簡(jiǎn)單,但是其內(nèi)部的實(shí)現(xiàn)包含了很多的數(shù)學(xué)與算法知識(shí),我們只是通過其簡(jiǎn)單的API就能各種復(fù)雜的功能。關(guān)于如何將目前說到的這些在具體的項(xiàng)目中進(jìn)行實(shí)踐與集成 后面會(huì)來介紹,首先我們能夠先了解一些技術(shù)一起能解決上面問題,理解了原理與目的,使用也就不是難事。

到此這篇關(guān)于Java利用布隆過濾器實(shí)現(xiàn)快速檢查元素是否存在的文章就介紹到這了,更多相關(guān)Java布隆過濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java子線程解決獲取主線程的request對(duì)象問題

    java子線程解決獲取主線程的request對(duì)象問題

    這篇文章主要介紹了java子線程解決獲取主線程的request對(duì)象問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之KMP算法

    Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之KMP算法

    在很多地方也都經(jīng)??吹街v解KMP算法的文章,看久了好像也知道是怎么一回事,但總感覺有些地方自己還是沒有完全懂明白。這兩天花了點(diǎn)時(shí)間總結(jié)一下,有點(diǎn)小體會(huì),我希望可以通過我自己的語(yǔ)言來把這個(gè)算法的一些細(xì)節(jié)梳理清楚,也算是考驗(yàn)一下自己有真正理解這個(gè)算法
    2022-02-02
  • 關(guān)于java.io.EOFException產(chǎn)生的原因以及解決方案

    關(guān)于java.io.EOFException產(chǎn)生的原因以及解決方案

    文章總結(jié):EOFException異常通常發(fā)生在嘗試從空的ObjectInputStream對(duì)象中讀取數(shù)據(jù)時(shí),解決方法是在finally語(yǔ)句中添加判斷,確保objectInputStream不為空后再進(jìn)行關(guān)閉操作,在處理1.txt文件為空的情況時(shí),捕獲EOFException可以避免程序終止,并且不會(huì)拋出空指針異常
    2025-01-01
  • Java利用InputStream類實(shí)現(xiàn)文件讀取與處理

    Java利用InputStream類實(shí)現(xiàn)文件讀取與處理

    在Java開發(fā)中,輸入流(InputStream)是一個(gè)非常重要的概念,它涉及到文件讀寫、網(wǎng)絡(luò)傳輸?shù)榷鄠€(gè)方面,InputStream類是Java中輸入流的抽象基類,定義了讀取輸入流數(shù)據(jù)的方法,本文將以InputStream類為切入點(diǎn),介紹Java中的輸入流概念及其應(yīng)用,需要的朋友可以參考下
    2023-11-11
  • Java:

    Java:"失效"的private修飾符

    本文主要介紹Java 失效的private修飾符,這里整理了相關(guān)資料說明private 修飾符的作用,如何使用并與C++ 做比較,有興趣的小伙伴可以參考下
    2016-08-08
  • Java設(shè)置session超時(shí)的幾種方式總結(jié)

    Java設(shè)置session超時(shí)的幾種方式總結(jié)

    這篇文章主要介紹了Java設(shè)置session超時(shí)的幾種方式總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java實(shí)現(xiàn)經(jīng)典捕魚達(dá)人游戲的示例代碼

    Java實(shí)現(xiàn)經(jīng)典捕魚達(dá)人游戲的示例代碼

    《捕魚達(dá)人》是一款以深海狩獵為題材的休閑競(jìng)技游戲。本文將利用Java實(shí)現(xiàn)這一經(jīng)典的游戲,文中采用了swing技術(shù)進(jìn)行了界面化處理,需要的可以參考一下
    2022-02-02
  • SpringBoot工程搭建打包、啟動(dòng)jar包和war包的教程圖文詳解

    SpringBoot工程搭建打包、啟動(dòng)jar包和war包的教程圖文詳解

    這篇文章主要介紹了SpringBoot工程搭建打包、啟動(dòng)jar包和war包的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Spring Boot項(xiàng)目添加外部Jar包以及配置多數(shù)據(jù)源的完整步驟

    Spring Boot項(xiàng)目添加外部Jar包以及配置多數(shù)據(jù)源的完整步驟

    這篇文章主要給大家介紹了關(guān)于Spring Boot項(xiàng)目添加外部Jar包以及配置多數(shù)據(jù)源的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    HTTP 基本認(rèn)證是一種簡(jiǎn)單的認(rèn)證方法,本文主要介紹了JAVA中HTTP基本認(rèn)證(Basic Authentication),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07

最新評(píng)論

宝鸡市| 金溪县| 台东县| 万年县| 沙雅县| 沈丘县| 定南县| 无棣县| 利辛县| 博乐市| 兴义市| 班戈县| 固阳县| 安阳县| 沿河| 江川县| 乌拉特中旗| 潮安县| 彰武县| 璧山县| 囊谦县| 衢州市| 郑州市| 宿州市| 靖西县| 玉溪市| 商城县| 临湘市| 长宁县| 合作市| 高清| 独山县| 滕州市| 乡城县| 安阳县| 扎兰屯市| 宜春市| 繁峙县| 文安县| 高平市| 永清县|