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

布隆過濾器面試如何快速判斷元素是否在集合里

 更新時(shí)間:2022年03月10日 08:49:07   作者:Q.E.D  
這篇文章主要為大家介紹了布隆過濾器面試中如何快速判斷元素是否在集合里的完美回復(fù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

如何快速判斷一個(gè)元素是不是在一個(gè)集合里?這個(gè)題目是我最近面試的時(shí)候常問的一個(gè)問題,這個(gè)問題不同人都有很多不同的回答。

今天想介紹一個(gè)很少有人會提及到的方案,那就是借助布隆過濾器。

1、什么叫布隆過濾器

布隆過濾器(Bloom Filter)是一個(gè)叫做 Bloom 的老哥于1970年提出的。

實(shí)際上可以把它看作由二進(jìn)制向量(或者說位數(shù)組)和一系列隨機(jī)映射函數(shù)(哈希函數(shù))兩部分組成的數(shù)據(jù)結(jié)構(gòu)。

它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間都比一般的算法要好的多,缺點(diǎn)是有一定的誤識別率和刪除困難。

圖片

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

先來一張圖

圖片

 布隆過濾器算法主要思想就是利用 n 個(gè)哈希函數(shù)進(jìn)行 hash 過后,得到不同的哈希值,根據(jù) hash 映射到數(shù)組(這個(gè)數(shù)組的長度可能會很長很長)的不同的索引位置上,然后將相應(yīng)的索引位上的值設(shè)置為1。

判斷該元素是否出現(xiàn)在集合中,就是利用k個(gè)不同的哈希函數(shù)計(jì)算哈希值,看哈希值對應(yīng)相應(yīng)索引位置上面的值是否是1,如果有1個(gè)不是1,說明該元素不存在在集合中。

但是也有可能判斷元素在集合中,但是元素不在,這個(gè)元素所有索引位置上面的1都是別的元素設(shè)置的,這就導(dǎo)致一定的誤判幾率(這就是為什么上面是活可能在一個(gè)集合中的根本原因,因?yàn)闀嬖谝欢ǖ?hash 沖突)。

注意:誤判率越低,相應(yīng)的性能就會越低。

3、作用

布隆過濾器是可以用于判斷一個(gè)元素是不是(可能)在一個(gè)集合里,并且相比于其它的數(shù)據(jù)結(jié)構(gòu),布隆過濾器在空間和時(shí)間方面都有巨大的優(yōu)勢。

注意上面的一個(gè)詞:可能。這里先預(yù)留一個(gè)懸念,下文會詳細(xì)分析到。

判斷給定數(shù)據(jù)是否存在

防止緩存穿透(判斷請求的數(shù)據(jù)是否有效避免直接繞過緩存請求數(shù)據(jù)庫)等等、郵箱的垃圾郵件過濾、黑名單功能等等。

4、具體實(shí)現(xiàn)

看完了布隆過濾器的算法思想,那就開始具體的實(shí)現(xiàn)的講解。

我先來舉個(gè)例子,假設(shè)有旺財(cái)和小強(qiáng)兩個(gè)字符串,他們分別經(jīng)過三次的 hash 算法,然后根據(jù) hash 的結(jié)果將對應(yīng)的數(shù)組(假設(shè)數(shù)組長度為 16)的索引位置的值置為1,先來看下旺財(cái)這個(gè)詞組:

圖片

旺財(cái)經(jīng)過三次 hash 過后,值分別為2,4,6 那么根據(jù)可以得到索引值分別為 2、4、6,于是就將該數(shù)組的索引(2、4、6)位置的值置為1,其余當(dāng)做是0,現(xiàn)在假設(shè)需要查找旺財(cái) ,同樣經(jīng)過這個(gè)三個(gè)hash 然后發(fā)現(xiàn)得到的索引 2、4、6對應(yīng)的位置的值都為1,那么可以判斷旺財(cái)可能是存在的。

接著有將小強(qiáng)插入到布隆過濾器中,實(shí)際的過程和上面的一樣,假設(shè)得到的下標(biāo)是 1、3、5

圖片

拋開旺財(cái)?shù)拇嬖冢?qiáng)此時(shí)是這樣子在布隆過濾器中的,結(jié)合旺財(cái)和小強(qiáng)實(shí)際的數(shù)組是這樣子的:

圖片

 現(xiàn)在有來一個(gè)數(shù)據(jù):9527,現(xiàn)在要求是判斷 9527 是否存在,假設(shè)9527 經(jīng)過三次 hash 過后得到的下標(biāo)分別為:5、6、7。結(jié)果發(fā)現(xiàn)下標(biāo)為 7 的位置的值為0,那么可以肯定的判斷出,9527 一定不存在。

接著又來了一個(gè) 國產(chǎn)007,經(jīng)過三次 hash 過后得到的下標(biāo)分別為:2、3、5,結(jié)果發(fā)現(xiàn) 2、3、5下標(biāo)對應(yīng)的值全是1,于是可以大致判斷出 國產(chǎn)007可能存在。但是實(shí)際上經(jīng)過我們剛剛的演示,國產(chǎn)007 根本就不存在,之所以 2、3、5 索引位置的值為1 ,那是因?yàn)槠渌臄?shù)據(jù)設(shè)置的。

說到這里,不知道大家有沒有明白布隆過濾器的作用。

5、代碼的實(shí)現(xiàn)

作為 java 程序員,我們真的是很幸福了,我們使用到很多的框架和工具,基本都被封裝好了,布隆過濾器,我們就使用 google 封裝好的工具類。當(dāng)然還有其他方法,大家可以探索探索。

首先添加依賴

<!--布隆過濾依賴-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>25.1-jre</version>
</dependency>

代碼的實(shí)現(xiàn)

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.Charset;
public class BloomFilterDemo {
        public static void main(String[] args) {
        /**
         * 創(chuàng)建一個(gè)插入對象為一億,誤報(bào)率為0.01%的布隆過濾器
         * 不存在一定不存在
         * 存在不一定存在
         * ----------------
         *  Funnel 對象:預(yù)估的元素個(gè)數(shù),誤判率
         *  mightContain :方法判斷元素是否存在
         */
        BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 100000000, 0.0001);
        bloomFilter.put("死");
        bloomFilter.put("磕");
        bloomFilter.put("Redis");
        System.out.println(bloomFilter.mightContain("Redis"));
        System.out.println(bloomFilter.mightContain("Java"));
    }
}

 具體的解釋已經(jīng)寫在注釋中了。到這里相信大家一定明白了布隆過濾器和其怎么使用了。

6、實(shí)戰(zhàn)

我們來模擬這樣的場景:通過布隆過濾器來解決緩存穿透。

首先你的知道什么叫緩存穿透吧?

緩存穿透是指用戶訪問一個(gè)緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),因?yàn)榫彺嬷胁淮嬖?,所以就會去訪問數(shù)據(jù)庫,如果并發(fā)很高。很容易會擊垮數(shù)據(jù)庫

那布隆過濾器是如何解決這個(gè)問題的呢?他

的原理是這樣子的:將數(shù)據(jù)庫中所有的查詢條件,放入布隆過濾器中,當(dāng)一個(gè)查詢請求過來時(shí),先經(jīng)過布隆過濾器進(jìn)行查,如果判斷請求查詢值存在,則繼續(xù)查;如果判斷請求查詢不存在,直接丟棄。

其代碼如下:

String get(String key) {
    String value = redis.get(key);     
    if (value  == null) {
        if(!bloomfilter.mightContain(key)){
            return null; 
        }else{
            value = db.get(key); 
            redis.set(key, value); 
        }    
    }
    return value;
}

7、小結(jié)

本文詳細(xì)介紹了布隆過濾器是什么?有什么作用?實(shí)現(xiàn)原理以及從代碼層面多方面來闡述布隆過濾器。希望能為各位在學(xué)習(xí)進(jìn)階的路上添磚加瓦。

以上就是布隆過濾器面試如何快速判斷元素是否在集合里的詳細(xì)內(nèi)容,更多關(guān)于布隆過濾器面試判斷元素是否在集合里的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java Spring登錄練習(xí)詳解

    Java Spring登錄練習(xí)詳解

    這篇文章主要介紹了Java編程實(shí)現(xiàn)spring簡單登錄的練習(xí),具有一定參考價(jià)值,需要的朋友可以了解下,希望能夠給你帶來幫助
    2021-10-10
  • Java獲取文件路徑常用方法解析

    Java獲取文件路徑常用方法解析

    這篇文章主要介紹了Java獲取文件路徑常用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java使用數(shù)組實(shí)現(xiàn)ArrayList的動態(tài)擴(kuò)容的方法

    Java使用數(shù)組實(shí)現(xiàn)ArrayList的動態(tài)擴(kuò)容的方法

    這篇文章主要介紹了Java使用數(shù)組實(shí)現(xiàn)ArrayList的動態(tài)擴(kuò)容的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • IDEA版使用Java操作Redis數(shù)據(jù)庫的方法

    IDEA版使用Java操作Redis數(shù)據(jù)庫的方法

    這篇文章主要介紹了IDEA版使用Java操作Redis數(shù)據(jù)庫的方法,首先需要下載jedis.jar包,然后再工程中設(shè)置具體操作步驟跟隨小編一起學(xué)習(xí)下吧
    2021-08-08
  • 解決使用RestTemplate時(shí)報(bào)錯(cuò)RestClientException的問題

    解決使用RestTemplate時(shí)報(bào)錯(cuò)RestClientException的問題

    這篇文章主要介紹了解決使用RestTemplate時(shí)報(bào)錯(cuò)RestClientException的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • PageHelper插件實(shí)現(xiàn)一對多查詢時(shí)的分頁問題

    PageHelper插件實(shí)現(xiàn)一對多查詢時(shí)的分頁問題

    這篇文章主要介紹了PageHelper插件實(shí)現(xiàn)一對多查詢時(shí)的分頁問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • RabbitMQ的消息確認(rèn)機(jī)制的詳細(xì)總結(jié)

    RabbitMQ的消息確認(rèn)機(jī)制的詳細(xì)總結(jié)

    RabbitMQ消息確認(rèn)機(jī)制指的是在消息傳遞過程中,發(fā)送方發(fā)送消息后,接收方需要對消息進(jìn)行確認(rèn),以確保消息被正確地接收和處理,本文就講給大家詳解介紹RabbitMQ的幾種消息確認(rèn)機(jī)制,需要的朋友可以參考下
    2023-07-07
  • SpringBoot+actuator和admin-UI實(shí)現(xiàn)監(jiān)控中心方式

    SpringBoot+actuator和admin-UI實(shí)現(xiàn)監(jiān)控中心方式

    這篇文章主要介紹了SpringBoot+actuator和admin-UI實(shí)現(xiàn)監(jiān)控中心方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java實(shí)現(xiàn)線程調(diào)度器和時(shí)間分片

    java實(shí)現(xiàn)線程調(diào)度器和時(shí)間分片

    線程調(diào)度器和時(shí)間分片是多線程編程和操作系統(tǒng)設(shè)計(jì)中的核心概念,本文主要介紹了java實(shí)現(xiàn)線程調(diào)度器和時(shí)間分片,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • 詳解Http協(xié)議以及post與get區(qū)別

    詳解Http協(xié)議以及post與get區(qū)別

    這篇文章主要介紹了詳解Http協(xié)議以及post與get區(qū)別,通過分別說明Http協(xié)議以及get與post各自的概念,再到兩者作比較有著詳細(xì)的說明,希望對你有所幫助
    2021-06-06

最新評論

承德县| 祁东县| 长宁区| 苍山县| 林口县| 吴忠市| 龙胜| 武宣县| 措美县| 榆林市| 扎囊县| 东乌珠穆沁旗| 津市市| 沙雅县| 吴忠市| 德惠市| 双辽市| 大同县| 洪江市| 乐都县| 黑水县| 浠水县| 西藏| 卢龙县| 茶陵县| 华阴市| 永州市| 钟祥市| 湖南省| 礼泉县| 大余县| 米泉市| 丽江市| 望江县| 江津市| 曲水县| 安顺市| 上犹县| 延川县| 夏邑县| 武陟县|