欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

Guava BloomFilter

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

基本概念

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

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

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

也就是布隆過濾器

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

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

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

應(yīng)用場景

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

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

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

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

優(yōu)缺點

優(yōu)點

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

缺點

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

實現(xiàn)原理

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

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

????????public?<T>?boolean?put(@ParametricNullness?T?object,?Funnel<??super?T>?funnel,?int?numHashFunctions,?LockFreeBitArray?bits)?{
????????????long?bitSize?=?bits.bitSize();?//?位數(shù)組,可以通過redis來實現(xiàn)分布式的布隆過濾器
????????????long?hash64?=?Hashing.murmur3_128().hashObject(object,?funnel).asLong();?//通過funnel將對象轉(zhuǎn)換成基本類型并計算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相似,計算的過程相同,不同的是值的判斷

????????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;
????????}

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

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

為什么判斷元素一定不在集合中呢?很顯然,如果一個元素存在,則該元素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->{
????????????//?正常情況下全部失敗,但是會有?20%的返回true
????????????System.out.println(?id?+?":"?+?filter.mightContain(?id+1?));
????????});
????}

流程很簡單:

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

結(jié)束語

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

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

相關(guān)文章

  • 使用JAVA判斷凸多邊形的示例代碼

    使用JAVA判斷凸多邊形的示例代碼

    本文提供了使用JAVA判斷凸多邊形的示例代碼供大家參考學(xué)習(xí),需要的朋友可以看一下
    2013-11-11
  • 微信小程序完整項目實戰(zhàn)記錄(前端+SpringBoot后端)

    微信小程序完整項目實戰(zhàn)記錄(前端+SpringBoot后端)

    隨著微信小程序的流行,越來越多的開發(fā)者開始涉足小程序開發(fā),下面這篇文章主要給大家介紹了關(guān)于微信小程序完整項目實戰(zhàn)的相關(guān)資料,項目包括前端+SpringBoot后端,需要的朋友可以參考下
    2024-09-09
  • Java遠程共享目錄的操作代碼

    Java遠程共享目錄的操作代碼

    這篇文章主要介紹了java操作遠程共享目錄的實現(xiàn)代碼,非常不粗,具有參考借鑒價值,需要的朋友可以參考下
    2017-08-08
  • Java中常用的設(shè)計模式之建造者模式詳解

    Java中常用的設(shè)計模式之建造者模式詳解

    這篇文章主要為大家詳細介紹了Java中常用的設(shè)計模式之建造者模式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Hibernate中5個核心接口知識點整理

    Hibernate中5個核心接口知識點整理

    在本篇文章里小編給大家整理的是一篇關(guān)于Hibernate中5個核心接口知識點整理等內(nèi)容,有興趣的朋友們跟著學(xué)習(xí)參考下。
    2021-08-08
  • Spring Bean的生命周期詳細介紹

    Spring Bean的生命周期詳細介紹

    這篇文章主要介紹了Spring Bean的生命周期的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • 一文帶你看懂Android動畫的實現(xiàn)原理

    一文帶你看懂Android動畫的實現(xiàn)原理

    動畫是 Android 應(yīng)用程序中重要的交互特性,ndroid 提供了多種動畫效果,包括平移、縮放、旋轉(zhuǎn)和透明度等,它們可以通過代碼或 XML 來實現(xiàn),本文將介紹 Android 動畫的原理和實現(xiàn)方法,并提供一些示例,需要的朋友可以參考下
    2023-07-07
  • 跨域解決方案Jsonp原理解析

    跨域解決方案Jsonp原理解析

    這篇文章主要介紹了跨域解決方案Jsonp原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • java實現(xiàn)九宮格游戲

    java實現(xiàn)九宮格游戲

    這篇文章主要為大家詳細介紹了java實現(xiàn)九宮格游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • 詳解@ConditionalOnMissingBean注解的作用

    詳解@ConditionalOnMissingBean注解的作用

    這篇文章主要介紹了詳解@ConditionalOnMissingBean注解的作用,@ConditionalOnMissingBean,它是修飾bean的一個注解,主要實現(xiàn)的是,當(dāng)你的bean被注冊之后,如果而注冊相同類型的bean,就不會成功,它會保證你的bean只有一個,需要的朋友可以參考下
    2023-10-10

最新評論