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

場景題:假設有40億QQ號,但只有1G內存,如何實現判重?

數據庫 MySQL
使用 MySQL 數據庫判重,或使用 List.contains() 或 Set.contains() 判重就不行了,因為數據量太大會導致內存放不下,或查詢速度太慢等問題。

當數據量比較大時,使用常規(guī)的方式來判重就不行了。例如,使用 MySQL 數據庫判重,或使用 List.contains() 或 Set.contains() 判重就不行了,因為數據量太大會導致內存放不下,或查詢速度太慢等問題。

1.空間占用量預測

正常情況下,如果將 40 億 QQ 號存儲在 Java 中的 int 類型的話,一個 int 占 4 字節(jié)(byte)那么 40 億占用空間大小為:

4000000000*4/1024/1024/1024=14.9 GB

1GB=1024MB,1MB=1024KB,1KB=1024B(byte)

所以,我們無法使用正常的手段進行 40 億 QQ 號的存儲和去重判斷,那怎么實現呢?

2.解決方案

此問題的常見解決方案有兩種:

  • 使用位數組 BitMap 實現判重。
  • 使用布隆過濾器實現判重。

具體來說。

(1)位數組實現判重

位數組是指使用位(bit)組成的數組,每個 QQ 號使用 1 位(bit)來存儲,如下圖所示:

其中下標用來標識具體的數字,例如以上圖片標識 1、3 數字存在,如果值為 0 表示不存在,這樣的話 40 億占用的位數組空間位 40 億 bit,也就是 4000000000/1024/1024/1024/8=0.465 GB,不到 1G 的內存就可以存儲 40 億 QQ 號了,查詢某個 QQ 號是否在線,只需要看這個 QQ 下標對應的位置是否為 1,1 表示存在,0 表示不存在。

位數組代碼實現

位數組可以使用 Java 自帶的 BitSet 來實現,它位于 java.util 包中,具體實現代碼如下:

import java.util.BitSet;

public class BitmapExample {
    public static void main(String[] args) {
        // 創(chuàng)建一個BitSet實例
        BitSet bitmap = new BitSet();

        // 設置第5個位置為1,表示第5個元素存在
        bitmap.set(5);

        // 檢查第5個位置是否已設置
        boolean exists = bitmap.get(5);
        System.out.println("Element exists: " + exists);  // 輸出: Element exists: true

        // 設置從索引10到20的所有位置為1
        bitmap.set(10, 21);  // 參數是包含起始點和不包含終點的區(qū)間

        // 計算bitset中所有值為1的位的數量,相當于計算設置了的元素個數
        int count = bitmap.cardinality();
        System.out.println("Number of set bits: " + count);

        // 清除第5個位置
        bitmap.clear(5);

        // 判斷位圖是否為空
        boolean isEmpty = bitmap.isEmpty();
        System.out.println("Is the bitset empty? " + isEmpty);
    }
}

(2)布隆過器實現

布隆過濾器是基于位數組實現的,它是一種高效的數據結構,由布隆在 1970 年提出。它主要用于判斷一個元素可能是否存在于集合中,其核心特性包括高效的插入和查詢操作,但存在一定的假陽性(False Positives)可能性。

布隆過濾器實現如下圖所示:

根據 key 值計算出它的存儲位置,然后將此位置標識全部標識為 1(未存放數據的位置全部為 0),查詢時也是查詢對應的位置是否全部為 1,如果全部為 1,則說明數據是可能存在的,否則一定不存在。

布隆過器特性:如果布隆過濾器說一個元素不在集合中,那么它一定不在這個集合中;但如果它說一個元素在集合中,則有可能是不存在的(存在誤差,假陽性)。

布隆過器代碼實現

布隆過濾器的常見實現有以下幾種方式:

使用 Google Guava BloomFilter 實現布隆過濾器,具體實現代碼如下:

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
public class BloomFilterExample {
    public static void main(String[] args) {
        // 創(chuàng)建一個布隆過濾器,設置期望插入的數據量為10000,期望的誤判率為0.01
        BloomFilter<String> bloomFilter = 
        BloomFilter.create(Funnels.unencodedCharsFunnel(), 10000, 0.01);
        // 向布隆過濾器中插入數據
        bloomFilter.put("data1");
        bloomFilter.put("data2");
        bloomFilter.put("data3");
        // 查詢元素是否存在于布隆過濾器中
        System.out.println(bloomFilter.mightContain("data1")); // true
        System.out.println(bloomFilter.mightContain("data4")); // false
    }
}

使用 Hutool 框架 BitMapBloomFilter 實現布隆過濾器,如下代碼所示:

// 初始化
BitMapBloomFilter filter = new BitMapBloomFilter(10);
// 存放數據
filter.add("123");
filter.add("abc");
filter.add("ddd");
// 查找
filter.contains("abc");

使用 Redisson 框架中的 RBloomFilter 實現布隆過濾器,如下代碼所示:

Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redissonClient = Redisson.create(config);
// 創(chuàng)建布隆過濾器,設置名稱和期望容量與誤報率
RBloomFilter<String> bloomFilter = 
redissonClient.getBloomFilter("myBloomFilter");
bloomFilter.tryInit(10000, 0.03); // 期望容量 10000,誤報率 3%
// 添加元素到布隆過濾器
String element1 = "element1";
bloomFilter.add(element1);
// 判斷元素是否存在
boolean mightExist = bloomFilter.contains(element1);
System.out.println("元素 " + element1 + " 可能存在: " + mightExist);
String element2 = "element2";
boolean mightExist2 = bloomFilter.contains(element2);
System.out.println("元素 " + element2 + " 可能存在: " + mightExist2);

其中 Google Guava BloomFilter 和 Hutool 框架 BitMapBloomFilter 為單機版的布隆過濾器實現,不適用分布式環(huán)境。分布式環(huán)境要使用 Redisson 框架中的 RBloomFilter 來實現布隆過濾器,因為它的數據是保存在 Redis 中間件的,而中間件天生支持分布式系統。

小結

位數組和布隆過濾器的區(qū)別如下:

  • 位數組:沒有誤判,但空間利用率低。
  • 布隆過濾器:空間利用率高,但存在對已經存在的數據的誤判(不存在的數據沒有誤判)。

因此,如果對精準度要求高可以使用位數組;如果對空間要求苛刻,可以考慮布隆過濾器。

責任編輯:姜華 來源: 磊哥和Java
相關推薦

2025-03-26 02:22:00

2024-03-11 16:01:29

BitMap數據去重開發(fā)

2023-09-18 16:59:06

數據布隆過濾器

2024-06-03 06:45:18

2024-03-06 09:22:23

C#數據庫判重

2021-12-08 09:53:50

騰訊QQ號碼重復

2024-02-19 11:49:23

JavaBitMap類型

2023-12-27 07:56:29

內存哈希算法排序算法

2016-12-21 15:33:11

中國移動4G尚冰

2025-01-14 16:14:10

2010-03-01 09:03:53

谷歌寬帶光纖

2009-09-18 09:57:01

華碩服務器促銷

2021-04-21 18:57:16

二進制存儲空間

2012-05-21 18:13:42

360特供機

2019-03-28 06:31:01

2019-03-10 15:54:22

5G通信4G

2022-02-09 22:49:06

1G移動通信

2011-10-20 13:41:57

神舟臺式機

2020-04-27 09:42:11

5G6G通信
點贊
收藏

51CTO技術棧公眾號