java中的算法(一致性hash算法和數據結構的問題)

一、一致性hash算法

對我們有什麼啓發?

一致性hash,本質就是把數據分散在(2^32-1) 圓形的槽裏面!
假設我們的(2^32-1) 每個槽裏面,只存儲一個bit,那我們佔用的內存之後
(2^32)-1 bit 大
1 個int = 4 個byte
1 個byte = 8bit
1 int = 32 個bit

二、問題的引入?

怎麼判斷1億 數據裏面是否存在某個數據?要求算法的複雜度,控制在常數範圍內!
14億人身份證號碼,怎麼快速判斷某個身份證號碼在這個裏面?

2.1 解決方案1 HashSet

把14億個字符串存在在HashSet 裏面,使用HashSet的 判斷是否存在某個值解決

2.2 解決方案2 TreeSet 裏面

把14億個字符串存在在TreeSet 裏面,使用TreeSet 的 判斷是否存在某個值解決
在這裏插入圖片描述
速度問題:使用Hash>>Tree
佔用空間問題:若14個值都存儲滿,佔用大小基本是一樣的!

2.3 使用集合存儲字符串數據的優缺點

優點:非常簡單,我們可以直接是HashSet 來存儲
缺點:當我們的數據量約大,它的存儲的數據將無法估量,可能導致JVM 內存的移除

HashSet 和TreeSet 直接存儲字符串佔用的內存太大了,我們需要去選擇別的結構了

三、引入位集合

3.1 圖示

在這裏插入圖片描述

3.2 特點

集合裏面只能存儲0/1 ,
每個點都佔用1 個bit

四、Hash

4.1 hash

什麼叫hash?
Hash 就是爲把某個值,映射在一個有序的長度上面,得到一個映射值
在這裏插入圖片描述

4.2 hash 和hashCode

在一段長度的位置值
在這裏插入圖片描述
和HashCode的關係:

HashCode 不等於該位置的值,
HashCode 一般是個非常特殊的值,是通過一個質數做變化得來的?
在這裏插入圖片描述
該值不容易重複,該值算出來可以很多!

什麼是位置的pos:
位置的值,不等於hashCode 的值:
比如我們的長度有20 ,但是你的hashCode 是100 ;
我們沒有放下你,需要一個變化?
怎麼把hashCode 值變成一個Pos的值?

Int pos = getPos(hashCode);
Int pos(){
 Int pos = hashCode & (len-1) ;
}

通過該方法我們可以把任意的hashCode 映射在我們的固定長度位置上面

4.3 怎麼解決Hash 衝突的問題

有2 個值,他們的hash值/pos值都是相同的?
Hash衝突怎麼搞?

4.3.1 拉鍊法解決

就是HashMap 裏面的解決思路

4.3.2 二次hash

我們若計算出來該值的hash 和之前的值有衝突,我們使用另一個hashCode函數在計算hashCode,得的不同的pos ,有新的pos

4.3.3 跳躍法

在這裏插入圖片描述
在這裏插入圖片描述

五、使用位集合存在字符串,並且判斷該字符串是否存儲在該位集合裏面

5.1 思維導圖

在這裏插入圖片描述

5.2 將上面的圖,使用代碼表示出來

在這裏插入圖片描述

5.3.1 新建HashCodeFun

public class HashCodeFun {

    /**
     * 質數,計算hashCode值的關鍵
     */
    private int seed ;

    public HashCodeFun(int seed){
        this.seed = seed ;
    }
    /**
     * 給一個value ,計算該value的hashCode
     * @param value
     * @return
     */
    public int hashCodeFun(String value) {
        char[] chars = value.toCharArray();
        int h = 0;

        if (h == 0 && chars.length > 0) {
            char val[] = chars;
            for (int i = 0; i < chars.length; i++) {
                h = seed * h + val[i];
            }
        }
        return h;
    }
}

5.3.2 新建Quesion類

public class Question {
    /**
     * 位集合的長度
     */
    private int len = 32 ;
    /**
     * 創建一個位集合
     */
    private BitSet bitSet = new BitSet(len) ;

    private int []seeds = new int[]{31,37,41,43};

    private HashCodeFun[] hashCodeFuns = new HashCodeFun[4] ;
    {
        for (int i = 0; i < seeds.length; i++) {
            hashCodeFuns[i] = new HashCodeFun(seeds[i]) ;
        }
    }


    /**
     * 往位集合裏面設置一個值
     * @param value
     */
    public void addValue(String value){
        for (HashCodeFun hashCodeFun : hashCodeFuns) { // 循環hashCode的方法
            int hashCode = hashCodeFun.hashCodeFun(value); // 通過質數計算HashCode的值
            int pos = hashCode & (len-1) ;
            System.out.println(pos);
            bitSet.set(pos,true);
        }
    }

    /**
     * 怎麼判斷該位集合裏是否存在某個值
     * 1 判斷集合裏面的代表該value的4 個點
     */
    public boolean existValue(String value){
        for (HashCodeFun hashCodeFun : hashCodeFuns) {
            int hashCode = hashCodeFun.hashCodeFun(value);
            int pos = hashCode & (len-1) ;
            if(!bitSet.get(pos)){ // 若該位集合上面的該點,沒有被佔用,
             return false ; // 有一個點不符合
            }
        }
        return  true ;
    }

    public static void main(String[] args) {
        Question question = new Question();
        question.addValue("mayun");
//        question.addValue("mahuateng");

        System.out.println(question.existValue("mahuateng"));

//        System.out.println(question.existValue("mahuateng"));
    }
}

5.3 hash 函數的本質是是啥?

Hash過程的本質是啥:
在這裏插入圖片描述
Hash函數的本質在於特徵的提取

做人臉識別:鼻子 + 嘴巴 + 耳朵 + 眼睛

鼻子 = Hash1(人臉);
嘴巴 = Hash2(人臉);
耳朵 = Hash3(人臉);
眼睛 = Hash4(人臉);

假設我們的hash函數可以做一個特徵的提取,
利用高斯函數疊加:得到一個具體的特徵
你的臉和劉德華的臉:
對比你們2個的鼻子,嘴巴,耳朵,眼睛

在人臉識別裏面,需要一個特徵的提取,在把字符串映射在位集合上,它的本質也是提取字符串某個特徵!

5.4 我們上面使用位集合存儲值,並且判斷位集合裏面是否有值,屬於BloomFilter的算法

5.6 作業

5.6.1 把今天Mycat的高可用測試成功

5.6.2 使用位集合存儲值,並且判斷值是否有,這個算法實現了

5.6.3 使用Redis 來實現我們上面寫的BloomFilter這個算法

提示:
1 bitset 在jvm的內存裏面,無法和別的jvm 共享
2 bitset 太大了,可能會佔用內存!
使用Redis 使用BloomFilter
在redis 裏面有個數據結構:BitMap
在這裏插入圖片描述

5.6.4 BitMap的結構

在這裏插入圖片描述

5.6.5 bitMap的操作

在這裏插入圖片描述

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章