溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java中的布隆過濾器怎么應(yīng)用

發(fā)布時間:2023-04-27 09:44:21 來源:億速云 閱讀:116 作者:zzz 欄目:開發(fā)技術(shù)

今天小編給大家分享一下Java中的布隆過濾器怎么應(yīng)用的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

什么是布隆過濾器

布隆過濾器(Bloom Filter)是一種空間效率非常高的隨機(jī)數(shù)據(jù)結(jié)構(gòu),它利用位數(shù)組(BitSet)表示一個集合,并通過一定數(shù)量的哈希函數(shù)將元素映射為位數(shù)組中的位置,用于檢查一個元素是否屬于這個集合。

實現(xiàn)的核心思想

對于一個元素,通過多個哈希函數(shù)生成多個哈希值,將對應(yīng)的位在位數(shù)組中設(shè)為 1,若多個哈希值對應(yīng)的位都為 1,則認(rèn)為該元素可能在集合中;若至少有一個哈希值對應(yīng)的位為 0,則該元素一定不在集合中。這種方法可以在較小的空間中實現(xiàn)高效的查找,但可能存在誤判率(false positive)。

怎么理解

一個典型的布隆過濾器包含三個參數(shù): 位數(shù)組的大?。创鎯υ氐膫€數(shù)); 哈希函數(shù)的個數(shù); 填充因子(即誤判率),即將元素數(shù)量與位數(shù)組大小的比值。

Java中的布隆過濾器怎么應(yīng)用

如上圖所示: 布隆過濾器的基本操作流程,包括初始化位數(shù)組和哈希函數(shù)、插入元素、檢查元素是否在集合中等。其中,每個元素都會被多個哈希函數(shù)映射到位數(shù)組中的多個位置,而在檢查元素是否在集合中時,需要確保所有對應(yīng)的位都被設(shè)置為 1,才會認(rèn)為該元素可能在集合中。

典型應(yīng)用場景

垃圾郵件過濾: 將所有的黑名單郵件對應(yīng)的哈希值在布隆過濾器中對應(yīng)的位置設(shè)為 1,對于每一封新郵件,將其哈希值在布隆過濾器中對應(yīng)的位置檢查是否都為 1,若是,則認(rèn)為該郵件是垃圾郵件,否則可能是正常郵件;

URL 去重: 將已經(jīng)抓取的 URL 對應(yīng)的哈希值在布隆過濾器中對應(yīng)的位置設(shè)為 1,對于每一條新的 URL,將其哈希值在布隆過濾器中對應(yīng)的位置檢查是否都為 1,若是,則認(rèn)為該 URL 已經(jīng)抓取過,否則需要進(jìn)行抓??;

緩存擊穿: 將緩存中存在的所有數(shù)據(jù)對應(yīng)的哈希值在布隆過濾器中對應(yīng)的位置設(shè)為 1,對于每一個查詢的鍵值,將其哈希值在布隆過濾器中對應(yīng)的位置檢查是否都為 1,若是,則認(rèn)為該鍵值存在于緩存中,否則需要從數(shù)據(jù)庫中查詢并將其添加到緩存中。

需要注意的是,布隆過濾器的誤判率會隨著位數(shù)組大小的增加而減小,但同時也會增加內(nèi)存開銷和計算時間。 為了方便理解布隆過濾器,下面用java代碼實現(xiàn)一個簡單的布隆過濾器:

import java.util.BitSet;

import java.util.Random;

 

public class BloomFilter {


  private BitSet bitSet;           // 位集,用于存儲哈希值

  private int bitSetSize;         // 位集大小

  private int numHashFunctions;   // 哈希函數(shù)數(shù)量

  private Random random;          // 隨機(jī)數(shù)生成器


  // 構(gòu)造函數(shù),根據(jù)期望元素數(shù)量和錯誤率計算位集大小和哈希函數(shù)數(shù)量

  public BloomFilter(int expectedNumItems, double falsePositiveRate) {

    this.bitSetSize = optimalBitSetSize(expectedNumItems, falsePositiveRate);

    this.numHashFunctions = optimalNumHashFunctions(expectedNumItems, bitSetSize);

    this.bitSet = new BitSet(bitSetSize);

    this.random = new Random();

  }


  // 根據(jù)期望元素數(shù)量和錯誤率計算最佳位集大小

  private int optimalBitSetSize(int expectedNumItems, double falsePositiveRate) {

    int bitSetSize = (int) Math.ceil(expectedNumItems * (-Math.log(falsePositiveRate) / Math.pow(Math.log(2), 2)));

    return bitSetSize;

  }

 
  // 根據(jù)期望元素數(shù)量和位集大小計算最佳哈希函數(shù)數(shù)量

  private int optimalNumHashFunctions(int expectedNumItems, int bitSetSize) {

    int numHashFunctions = (int) Math.ceil((bitSetSize / expectedNumItems) * Math.log(2));

    return numHashFunctions;

  }

 
  // 添加元素到布隆過濾器中

  public void add(String item) {

    // 計算哈希值

    int[] hashes = createHashes(item.getBytes(), numHashFunctions);

    // 將哈希值對應(yīng)的位設(shè)置為 true

    for (int hash : hashes) {

      bitSet.set(Math.abs(hash % bitSetSize), true);

    }

  }


  // 檢查元素是否存在于布隆過濾器中

  public boolean contains(String item) {

    // 計算哈希值

    int[] hashes = createHashes(item.getBytes(), numHashFunctions);

    // 檢查哈希值對應(yīng)的位是否都為 true

    for (int hash : hashes) {

      if (!bitSet.get(Math.abs(hash % bitSetSize))) {

        return false;

      }

    }

    return true;

  }


  // 計算給定數(shù)據(jù)的哈希值

  private int[] createHashes(byte[] data, int numHashes) {

    int[] hashes = new int[numHashes];

    int hash2 = Math.abs(random.nextInt());

    int hash3 = Math.abs(random.nextInt());

    for (int i = 0; i < numHashes; i++) {

      // 使用兩個隨機(jī)哈希函數(shù)計算哈希值

      hashes[i] = Math.abs((hash2 * i) + (hash3 * i) + i) % data.length;

    }

    return hashes;

  }

}

以上就是“Java中的布隆過濾器怎么應(yīng)用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI