自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java中的布隆過(guò)濾器,你知道嗎?

開(kāi)發(fā) 前端
布隆過(guò)濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中。它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都遠(yuǎn)遠(yuǎn)超過(guò)一般的算法,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。

原理

布隆過(guò)濾器(Bloom Filter)是1970年由伯頓·霍華德·布?。˙urton Howard Bloom)提出的。它實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù)。

布隆過(guò)濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中。它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都遠(yuǎn)遠(yuǎn)超過(guò)一般的算法,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。

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

布隆過(guò)濾器的原理是,當(dāng)一個(gè)元素被加入集合時(shí),通過(guò)K個(gè)散列函數(shù)將這個(gè)元素映射成一個(gè)位數(shù)組中的K個(gè)點(diǎn),把它們置為1。

圖片圖片

檢索時(shí),我們只要看看這些點(diǎn)是不是都是1就(大約)知道集合中有沒(méi)有它了:如果這些點(diǎn)有任何一個(gè)0,則被檢元素一定不在;如果都是1,則被檢元素很可能在。

圖片圖片

接下來(lái),我們看下在Java中怎么使用。

單機(jī)版:Guava

首先引入依賴(lài):

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

然后使用Guava中的BloomFilter類(lèi)開(kāi)始實(shí)現(xiàn):

@Test
public void testBloomFilter() {
    final List<String> itemsToInsert = Arrays.asList("apple", "banana", "cherry", "elderberry");

    // 創(chuàng)建布隆過(guò)濾器
    BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), 100, 0.01);
    // 當(dāng)前元素?cái)?shù)量為0
    Assertions.assertEquals(0, bloomFilter.approximateElementCount());

    // 向布隆過(guò)濾器中插入數(shù)據(jù)
    for (String item : itemsToInsert) {
        bloomFilter.put(item);
    }
    // 當(dāng)前元素?cái)?shù)量為4
    Assertions.assertEquals(4, bloomFilter.approximateElementCount());

    // 測(cè)試已插入的數(shù)據(jù)
    for (String item : itemsToInsert) {
        Assertions.assertTrue(bloomFilter.mightContain(item), "Item should be in the Bloom Filter: " + item);
    }

    // 測(cè)試未插入的數(shù)據(jù)
    final List<String> itemsNotInserted = Arrays.asList("grape", "orange", "peach", "quince", "raspberry");
    for (String item : itemsNotInserted) {
        Assertions.assertFalse(bloomFilter.mightContain(item), "Item should not be in the Bloom Filter: " + item);
    }
}

Guava實(shí)現(xiàn)的是單機(jī)版,雖然提供了文件寫(xiě)出的功能,可以將文件分發(fā)到分布式系統(tǒng)中,但是這種方式只能是補(bǔ)充。推薦只在單機(jī)場(chǎng)景中使用Guava的布隆過(guò)濾器。

如果想要在分布式服務(wù)中使用,可以選擇Redission。

分布式版:Redission

引入依賴(lài):

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.11.5</version>
</dependency>

使用Docker在本地啟一個(gè)Redis服務(wù),用來(lái)驗(yàn)證:

docker run -d -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest

然后編碼測(cè)試:

@Test
public void testBloomFilter() {
    // 使用Docker本地啟動(dòng)一個(gè)Redis服務(wù)用來(lái)測(cè)試:
    //  docker run -d -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest

    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");

    // 生成key是 myBloomFilter 的存儲(chǔ)
    // 會(huì)生成兩個(gè)key,"myBloomFilter"、"{myBloomFilter}:config"
    // "myBloomFilter"是string類(lèi)型,布隆過(guò)濾器的主存
    // "{myBloomFilter}:config"是hash結(jié)構(gòu),存儲(chǔ)元信息,比如大小size、期望容量expectedInsertions、誤報(bào)率falseProbability、使用的哈希函數(shù)數(shù)量hashIterations等。
    RBloomFilter<String> bloomFilter = Redisson.create(config)
            .getBloomFilter("myBloomFilter");

    // 初始化布隆過(guò)濾器,定義期望容量和誤報(bào)率
    bloomFilter.tryInit(1000000, 0.01);

    // 準(zhǔn)備一些測(cè)試數(shù)據(jù)
    final List<String> itemsToInsert = Arrays.asList("apple", "banana", "cherry", "elderberry");

    // 向布隆過(guò)濾器中插入數(shù)據(jù)
    for (String item : itemsToInsert) {
        bloomFilter.add(item);
    }

    // 測(cè)試已插入的數(shù)據(jù)
    for (String item : itemsToInsert) {
        Assertions.assertTrue(bloomFilter.contains(item), "Item should be in the Bloom Filter: " + item);
    }

    // 測(cè)試未插入的數(shù)據(jù)
    final List<String> itemsNotInserted = Arrays.asList("grape", "orange", "peach", "quince", "raspberry");
    for (String item : itemsNotInserted) {
        Assertions.assertFalse(bloomFilter.contains(item), "Item should not be in the Bloom Filter: " + item);
    }
}

使用Redission的RBloomFilter,會(huì)根據(jù)布隆過(guò)濾器名字在Redis中生成兩個(gè)key,比如上面代碼的名字是“myBloomFilter”,生成的配置為:

  • "myBloomFilter"是string類(lèi)型,布隆過(guò)濾器的主存,用來(lái)存儲(chǔ)二進(jìn)制數(shù)組;
  • "{myBloomFilter}:config"是hash結(jié)構(gòu),存儲(chǔ)元信息,比如大小size、期望容量expectedInsertions、誤報(bào)率falseProbability、使用的哈希函數(shù)數(shù)量hashIterations等。


責(zé)任編輯:武曉燕 來(lái)源: 看山的小屋
相關(guān)推薦

2024-01-05 09:04:35

隆過(guò)濾器數(shù)據(jù)結(jié)構(gòu)哈希函數(shù)

2025-02-08 17:30:00

布隆過(guò)濾器數(shù)據(jù)結(jié)構(gòu)

2024-09-18 10:08:37

2025-01-22 00:00:00

布隆過(guò)濾器二進(jìn)制

2024-03-15 11:21:22

布隆過(guò)濾器數(shù)據(jù)庫(kù)數(shù)據(jù)

2023-01-31 08:19:53

二進(jìn)制元素數(shù)量

2024-11-04 08:45:48

布隆過(guò)濾器元數(shù)據(jù)指紋值

2025-04-30 08:47:41

2020-10-29 07:16:26

布隆過(guò)濾器場(chǎng)景

2019-03-22 15:15:25

Redis緩存擊穿雪崩效應(yīng)

2022-03-21 08:31:07

布隆過(guò)濾器Redis過(guò)濾器原理

2021-09-03 06:33:24

布隆過(guò)濾器高并發(fā)

2024-09-25 17:44:08

2024-10-09 15:54:38

布隆過(guò)濾器函數(shù)

2021-03-06 14:41:07

布隆過(guò)濾器算法

2023-07-06 10:15:38

布隆過(guò)濾器優(yōu)化

2023-04-26 08:32:45

Redis布隆過(guò)濾器

2023-11-20 14:18:55

大數(shù)據(jù)布隆過(guò)濾器布谷鳥(niǎo)過(guò)濾器

2016-12-07 09:56:13

JavaFilter過(guò)濾器

2020-08-28 13:02:17

布隆過(guò)濾器算法
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)