亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

布隆過濾器的原理以及java 簡單實現(xiàn)

 更新時間:2020年11月25日 11:35:35   作者:未月廿三  
這篇文章主要介紹了布隆過濾器的原理以及java 簡單實現(xiàn),幫助大家更好的理解和學習Java,感興趣的朋友可以了解下

一.布隆過濾器

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

如果想判斷一個元素是不是在一個集合里,一般想到的是將集合中所有元素保存起來,然后通過比較確定。鏈表、樹、散列表(又叫哈希表,Hash table)等等數(shù)據(jù)結構都是這種思路。但是隨著集合中元素的增加,我們需要的存儲空間越來越大。同時檢索速度也越來越慢,上述三種結構的檢索時間復雜度分別為:O(n), O(log n), O(n/k)。

布隆過濾器的原理是,當一個元素被加入集合時,通過K個Hash函數(shù)將這個元素映射成一個位數(shù)組中的K個點,把它們置為1。檢索時,我們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢元素一定不在;如果都是1,則被檢元素很可能在。這就是布隆過濾器的基本思想。

布隆過濾器數(shù)據(jù)結構

布隆過濾器是一個 bit 向量或者說 bit 數(shù)組,長這樣:

如果我們要映射一個值到布隆過濾器中,我們需要使用多個不同的哈希函數(shù)生成多個哈希值,并對每個生成的哈希值指向的 bit 位置 1,例如針對值 “baidu” 和三個不同的哈希函數(shù)分別生成了哈希值 1、4、7,則上圖轉(zhuǎn)變?yōu)椋?/p>

值得注意的是,4 這個 bit 位由于兩個值的哈希函數(shù)都返回了這個 bit 位,因此它被覆蓋了?,F(xiàn)在我們?nèi)绻氩樵?“dianping” 這個值是否存在,哈希函數(shù)返回了 1、5、8三個值,結果我們發(fā)現(xiàn) 5 這個 bit 位上的值為 0,說明沒有任何一個值映射到這個 bit 位上,因此我們可以很確定地說 “dianping” 這個值不存在。而當我們需要查詢 “baidu” 這個值是否存在的話,那么哈希函數(shù)必然會返回 1、4、7,然后我們檢查發(fā)現(xiàn)這三個 bit 位上的值均為 1,那么我們可以說 “baidu” 存在了么?答案是不可以,只能是 “baidu” 這個值可能存在。

這是為什么呢?答案跟簡單,因為隨著增加的值越來越多,被置為 1 的 bit 位也會越來越多,這樣某個值 “taobao” 即使沒有被存儲過,但是萬一哈希函數(shù)返回的三個 bit 位都被其他值置位了 1 ,那么程序還是會判斷 “taobao” 這個值存在。

支持刪除么

目前我們知道布隆過濾器可以支持 add 和 isExist 操作,那么 delete 操作可以么,答案是不可以,例如上圖中的 bit 位 4 被兩個值共同覆蓋的話,一旦你刪除其中一個值例如 “tencent” 而將其置位 0,那么下次判斷另一個值例如 “baidu” 是否存在的話,會直接返回 false,而實際上你并沒有刪除它。

如何解決這個問題,答案是計數(shù)刪除。但是計數(shù)刪除需要存儲一個數(shù)值,而不是原先的 bit 位,會增大占用的內(nèi)存大小。這樣的話,增加一個值就是將對應索引槽上存儲的值加一,刪除則是減一,判斷是否存在則是看值是否大于0。

代碼簡單實現(xiàn)布隆過濾器

package com.jd.demo.test;

import java.util.Arrays;
import java.util.BitSet;
import java.util.concurrent.atomic.AtomicBoolean;

public class MyBloomFilter {
  //你的布隆過濾器容量
  private static final int DEFAULT_SIZE = 2 << 28;
  //bit數(shù)組,用來存放結果
  private static BitSet bitSet = new BitSet(DEFAULT_SIZE);
  //后面hash函數(shù)會用到,用來生成不同的hash值,可隨意設置,別問我為什么這么多8,圖個吉利
  private static final int[] ints = {1, 6, 16, 38, 58, 68};

  //add方法,計算出key的hash值,并將對應下標置為true
  public void add(Object key) {
    Arrays.stream(ints).forEach(i -> bitSet.set(hash(key, i)));
  }

  //判斷key是否存在,true不一定說明key存在,但是false一定說明不存在
  public boolean isContain(Object key) {
     boolean result = true;
    for (int i : ints) {
    	//短路與,只要有一個bit位為false,則返回false
      result = result && bitSet.get(hash(key, i));
    }
    return result;
  }

  //hash函數(shù),借鑒了hashmap的擾動算法
  private int hash(Object key, int i) {
    int h;
    return key == null ? 0 : (i * (DEFAULT_SIZE - 1) & ((h = key.hashCode()) ^ (h >>> 16)));
  }
}

測試

public static void main(String[] args) {
  MyNewBloomFilter myNewBloomFilter = new MyNewBloomFilter();
  myNewBloomFilter.add("張學友");
  myNewBloomFilter.add("郭德綱");
  myNewBloomFilter.add(666);
  System.out.println(myNewBloomFilter.isContain("張學友"));//true
  System.out.println(myNewBloomFilter.isContain("張學友 "));//false
  System.out.println(myNewBloomFilter.isContain("張學友1"));//false
  System.out.println(myNewBloomFilter.isContain("郭德綱"));//true
  System.out.println(myNewBloomFilter.isContain(666));//true
  System.out.println(myNewBloomFilter.isContain(888));//false
}

二.具體代碼使用

在實際應用當中,我們不需要自己去實現(xiàn)BloomFilter。可以使用Guava提供的相關類庫即可。

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>25.1-jre</version>
</dependency>12345

判斷一個元素是否在集合中

public class Test1 {

  private static int size = 1000000;

  private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);

  public static void main(String[] args) {
    for (int i = 0; i < size; i++) {
      bloomFilter.put(i);
    }

    long startTime = System.nanoTime(); // 獲取開始時間
    //判斷這一百萬個數(shù)中是否包含29999這個數(shù)
    if (bloomFilter.mightContain(29999)) {
      System.out.println("命中了");
    }
    long endTime = System.nanoTime();  // 獲取結束時間
    System.out.println("程序運行時間: " + (endTime - startTime) + "納秒");
  }

}

運行結果如下:

命中了
程序運行時間: 441616納秒

自定義錯誤率

public class Test3 {

  private static int size = 1000000;

  private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.01);

  public static void main(String[] args) {
    for (int i = 0; i < size; i++) {
      bloomFilter.put(i);
    }
    List<Integer> list = new ArrayList<Integer>(1000);
    // 故意取10000個不在過濾器里的值,看看有多少個會被認為在過濾器里
    for (int i = size + 10000; i < size + 20000; i++) {
      if (bloomFilter.mightContain(i)) {
        list.add(i);
      }
    }
    System.out.println("誤判的數(shù)量:" + list.size());
  }

}

運行結果如下:

誤判的數(shù)量:941

對于緩存宕機的場景,使用白名單或者布隆過濾器都有可能會造成一定程度的誤判。原因是除了Bloom Filter 本身有誤判率,宕機之前的緩存不一定能覆蓋到所有DB中的數(shù)據(jù),當宕機后用戶請求了一個以前從未請求的數(shù)據(jù),這個時候就會產(chǎn)生誤判。當然,緩存宕機時使用白名單/布隆過濾器作為應急的方式,這種情況應該也是可以忍受的。

以上就是布隆過濾器的原理以及java 簡單實現(xiàn)的詳細內(nèi)容,更多關于java 布隆過濾器的資料請關注腳本之家其它相關文章!

相關文章

  • Java畢業(yè)設計實戰(zhàn)之教室預訂管理系統(tǒng)的實現(xiàn)

    Java畢業(yè)設計實戰(zhàn)之教室預訂管理系統(tǒng)的實現(xiàn)

    這是一個使用了java+SpringBoot+Maven+Vue+mysql開發(fā)的教室預訂管理系統(tǒng),是一個畢業(yè)設計的實戰(zhàn)練習,具有教室預訂管理該有的所有功能,感興趣的朋友快來看看吧
    2022-02-02
  • 使用java?實現(xiàn)mqtt兩種常用方式

    使用java?實現(xiàn)mqtt兩種常用方式

    在開發(fā)MQTT時有兩種方式一種是使用Paho Java 原生庫來完成,一種是使用spring boot 來完成,這篇文章主要介紹了使用java?實現(xiàn)mqtt兩種方式,需要的朋友可以參考下
    2022-11-11
  • springboot應用訪問zookeeper的流程

    springboot應用訪問zookeeper的流程

    這篇文章主要介紹了springboot應用訪問zookeeper的流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 在spring中手寫全局異常攔截器

    在spring中手寫全局異常攔截器

    這篇文章主要介紹了如何在spring中手寫全局異常攔截器,幫助大家更好的理解和使用spring框架,感興趣的朋友可以了解下
    2020-11-11
  • java+testng+selenium的自動化測試實例

    java+testng+selenium的自動化測試實例

    這篇文章主要介紹了java+testng+selenium的自動化測試實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • springboot集成redis實現(xiàn)簡單秒殺系統(tǒng)

    springboot集成redis實現(xiàn)簡單秒殺系統(tǒng)

    這篇文章主要為大家詳細介紹了springboot集成redis實現(xiàn)簡單秒殺系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Java中枚舉類的用法示例詳解

    Java中枚舉類的用法示例詳解

    枚舉類型可以取代以往常量的定義方式,即將常量封裝在類或接口中。此外,枚舉類型還提供了安全檢查功能。本文就來和大家講講Java中枚舉類的用法,需要的可以參考一下
    2022-07-07
  • java 線程公平鎖與非公平鎖詳解及實例代碼

    java 線程公平鎖與非公平鎖詳解及實例代碼

    這篇文章主要介紹了java 線程公平鎖與非公平鎖詳解及實例代碼的相關資料,需要的朋友可以參考下
    2017-02-02
  • Java泛型和Class類用法示例

    Java泛型和Class類用法示例

    這篇文章主要介紹了Java泛型和Class類用法,結合實例形式分析了java使用泛型限制class類避免強制類型轉(zhuǎn)換相關操作技巧,需要的朋友可以參考下
    2019-07-07
  • SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務端)

    SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務端)

    這篇文章主要介紹了SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務端),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評論