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

Java中的布隆過濾器你真的懂了嗎

 更新時(shí)間:2023年04月26日 17:15:02   作者:平凡一只濤  
經(jīng)常會(huì)聽到大家說起布隆過濾器,但是很多人都只是聽過名字,卻并不知道其是怎么實(shí)現(xiàn)的。下面將詳細(xì)介紹一下布隆過濾器,并且使用簡(jiǎn)單的代碼演示

什么是布隆過濾器

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

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

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

怎么理解

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

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

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

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

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

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

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

import java.util.BitSet;
import java.util.Random;
public class BloomFilter {
??private BitSet bitSet; ??????????// 位集,用于存儲(chǔ)哈希值
??private int bitSetSize; ????????// 位集大小
??private int numHashFunctions; ??// 哈希函數(shù)數(shù)量
??private Random random; ?????????// 隨機(jī)數(shù)生成器
??// 構(gòu)造函數(shù),根據(jù)期望元素?cái)?shù)量和錯(cuò)誤率計(jì)算位集大小和哈希函數(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ù)期望元素?cái)?shù)量和錯(cuò)誤率計(jì)算最佳位集大小
??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ù)期望元素?cái)?shù)量和位集大小計(jì)算最佳哈希函數(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) {
????// 計(jì)算哈希值
????int[] hashes = createHashes(item.getBytes(), numHashFunctions);
????// 將哈希值對(duì)應(yīng)的位設(shè)置為 true
????for (int hash : hashes) {
??????bitSet.set(Math.abs(hash % bitSetSize), true);
????}
??}
??// 檢查元素是否存在于布隆過濾器中
??public boolean contains(String item) {
????// 計(jì)算哈希值
????int[] hashes = createHashes(item.getBytes(), numHashFunctions);
????// 檢查哈希值對(duì)應(yīng)的位是否都為 true
????for (int hash : hashes) {
??????if (!bitSet.get(Math.abs(hash % bitSetSize))) {
????????return false;
??????}
????}
????return true;
??}
??// 計(jì)算給定數(shù)據(jù)的哈希值
??private int[] createHashes(byte[] data, int numHashes) {
????int[] hashes = new int[numHashes];
????int hash1 = Math.abs(random.nextInt());
????int hash2 = Math.abs(random.nextInt());
????for (int i = 0; i < numHashes; i++) {
??????// 使用兩個(gè)隨機(jī)哈希函數(shù)計(jì)算哈希值
??????hashes[i] = Math.abs((hash1 * i) + (hash2 * i) + i) % data.length;
????}
????return hashes;
??}
}

以上就是Java中的布隆過濾器你真的懂了嗎的詳細(xì)內(nèi)容,更多關(guān)于Java布隆過濾器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring MVC傳遞接收參數(shù)方式小結(jié)

    Spring MVC傳遞接收參數(shù)方式小結(jié)

    大家在開發(fā)中經(jīng)常會(huì)用到Spring MVC Controller來接收請(qǐng)求參數(shù),主要常用的接收方式就是通過實(shí)體對(duì)象以及形參等方式、有些用于GET請(qǐng)求,有些用于POST請(qǐng)求,有些用于兩者,下面介紹幾種常見的Spring MVC傳遞接收參數(shù)的方式
    2021-11-11
  • Java Fork/Join框架

    Java Fork/Join框架

    Fork/Join框架是Java7中新增的一項(xiàng)特性,也是Java7平臺(tái)的其中一項(xiàng)主要改進(jìn)。下面我們就來簡(jiǎn)單探討下Java的Fork/Join框架
    2016-09-09
  • 重寫equals的同時(shí)為何要重寫hashCode?

    重寫equals的同時(shí)為何要重寫hashCode?

    這篇文章主要給大家介紹了關(guān)于重寫equals的同時(shí)為何要重寫hashCode的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 偵聽消息隊(duì)列的Message Listener類示例詳解

    偵聽消息隊(duì)列的Message Listener類示例詳解

    Spring AMQP 是基于 Spring 框架的AMQP消息解決方案,提供模板化的發(fā)送和接收消息的抽象層,提供基于消息驅(qū)動(dòng)的 POJO的消息監(jiān)聽等,簡(jiǎn)化了我們對(duì)于RabbitMQ相關(guān)程序的開發(fā),本文給大家介紹偵聽消息隊(duì)列的Message Listener類,感興趣的朋友一起看看吧
    2023-12-12
  • SWT(JFace)體驗(yàn)之FormLayout布局

    SWT(JFace)體驗(yàn)之FormLayout布局

    SWT(JFace)體驗(yàn)之FormLayout布局示例代碼。
    2009-06-06
  • logback之如何按日期和大小切分日志

    logback之如何按日期和大小切分日志

    這篇文章主要介紹了logback之如何按日期和大小切分日志問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 詳解快速排序算法中的區(qū)間劃分法及Java實(shí)現(xiàn)示例

    詳解快速排序算法中的區(qū)間劃分法及Java實(shí)現(xiàn)示例

    這篇文章主要介紹了詳解快速排序算法中的區(qū)間劃分法及Java實(shí)現(xiàn)示例,文中分別介紹了快排時(shí)兩種區(qū)間劃分的思路,需要的朋友可以參考下
    2016-04-04
  • java 中斷線程的幾種方式 interrupt()詳解

    java 中斷線程的幾種方式 interrupt()詳解

    中斷(Interrupt)一個(gè)線程意味著在該線程完成任務(wù)之前停止其正在進(jìn)行的一切,有效地中止其當(dāng)前的操作。這篇文章主要介紹了java 中斷線程的幾種方式 interrupt(),需要的朋友可以參考下
    2021-11-11
  • MyBatis基于pagehelper實(shí)現(xiàn)分頁原理及代碼實(shí)例

    MyBatis基于pagehelper實(shí)現(xiàn)分頁原理及代碼實(shí)例

    這篇文章主要介紹了MyBatis基于pagehelper實(shí)現(xiàn)分頁原理及代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java的布爾類型基本介紹

    Java的布爾類型基本介紹

    這篇文章主要介紹了Java的布爾類型,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10

最新評(píng)論