最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的Hashtable源碼詳細(xì)解析

 更新時間:2023年11月20日 09:40:34   作者:西瓜游俠  
這篇文章主要介紹了Java中的Hashtable源碼詳細(xì)解析,Hashtable 的函數(shù)都是同步的,這意味著它是線程安全的,它的key、value都不可以為null,此外,Hashtable中的映射不是有序的,需要的朋友可以參考下

1、簡介

和HashMap一樣,Hashtable 也是一個散列表,它存儲的內(nèi)容是鍵值對(key-value)映射。

Hashtable 繼承于Dictionary,實現(xiàn)了Map、Cloneable、java.io.Serializable接口。 Hashtable 的函數(shù)都是同步的,這意味著它是線程安全的它的key、value都不可以為null。此外,Hashtable中的映射不是有序的。

Hashtable 的實例有兩個參數(shù)影響其性能:初始容量加載因子。

容量:是哈希表中桶 的數(shù)量,初始容量 就是哈希表創(chuàng)建時的容量。注意,哈希表的狀態(tài)為 open:在發(fā)生“哈希沖突”的情況下,單個桶會存儲多個條目,這些條目必須按順序搜索。

加載因子:是對哈希表在其容量自動增加之前可以達(dá)到多滿的一個尺度(閾值)。初始容量和加載因子這兩個參數(shù)只是對該實現(xiàn)的提示。關(guān)于何時以及是否調(diào)用 rehash 方法的具體細(xì)節(jié)則依賴于該實現(xiàn)。

通常,默認(rèn)加載因子是 0.75, 這是在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查找某個條目的時間(在大多數(shù) Hashtable 操作中,包括 get 和 put 操作,都反映了這一點(diǎn))。

2、關(guān)鍵點(diǎn)

  • Hashtable繼承于Dictionary類,實現(xiàn)了Map接口。Map是”key-value鍵值對”接口,Dictionary是聲明了操作”鍵值對”函數(shù)接口的抽象類。
  • Hashtable是通過”拉鏈法“實現(xiàn)的哈希表。它包括幾個重要的成員變量:table, count, threshold, loadFactor, modCount。
    • table是一個Entry[]數(shù)組類型,而Entry實際上就是一個單向鏈表。哈希表的”key-value鍵值對”都是存儲在Entry數(shù)組中的。
    • count是Hashtable的大小,它是Hashtable保存的鍵值對的數(shù)量。
    • threshold是Hashtable的閾值,用于判斷是否需要調(diào)整Hashtable的容量。threshold的值=”容量*加載因子”。
    • loadFactor就是加載因子。
    • modCount是用來實現(xiàn)fail-fast機(jī)制的。

3、Hashtable數(shù)據(jù)存儲數(shù)組

    private transient Entry<?,?>[] table;

Hashtable中的key-value都是存儲在table數(shù)組中的。

4、數(shù)據(jù)節(jié)點(diǎn)Entry<K,V>的數(shù)據(jù)結(jié)構(gòu)

private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;  //hash值
        final K key;     //鍵
        V value;         //值
        Entry<K,V> next; //鏈表中下一個Entry的引用

        //Entry的構(gòu)造函數(shù)
        protected Entry(int hash, K key, V value, Entry<K,V> next) {
            this.hash = hash;
            this.key =  key;
            this.value = value;
            this.next = next;
        }

        @SuppressWarnings("unchecked")
        protected Object clone() {
            return new Entry<>(hash, key, value,
                                  (next==null ? null : (Entry<K,V>) next.clone()));
        }

        // Map.Entry Ops

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        //設(shè)置value。若value是null,則拋出異常。
        public V setValue(V value) {
            if (value == null)
                throw new NullPointerException();

            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        // 覆蓋equals()方法,判斷兩個Entry是否相等。
        // 若兩個Entry的key和value都相等,則認(rèn)為它們相等。
        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
               (value==null ? e.getValue()==null : value.equals(e.getValue()));
        }

        //Entry對象的hash值
        public int hashCode() {
            return hash ^ Objects.hashCode(value);
        }

        public String toString() {
            return key.toString()+"="+value.toString();
        }
    }

5、Hashtable的構(gòu)造函數(shù)

    // 指定“容量大小”和“加載因子”的構(gòu)造函數(shù)
    public Hashtable(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);

        if (initialCapacity==0)
            initialCapacity = 1;
        this.loadFactor = loadFactor;
        table = new Entry<?,?>[initialCapacity];
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    }

    // 指定“容量大小”的構(gòu)造函數(shù),加載因子使用默認(rèn)值0.75
    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    // 默認(rèn)構(gòu)造函數(shù),指定的容量大小是11,加載因子是0.75
    public Hashtable() {
        this(11, 0.75f);
    }

    // 包含“子Map”的構(gòu)造函數(shù)
    public Hashtable(Map<? extends K, ? extends V> t) {
        this(Math.max(2*t.size(), 11), 0.75f);
        // 將“子Map”的全部元素都添加到Hashtable中
        putAll(t);
    }

6、Hashtable的主要對外接口

6.1 clear()

clear() 的作用是清空Hashtable。它是將Hashtable的table數(shù)組的值全部設(shè)為null。

    public synchronized void clear() {
        Entry<?,?> tab[] = table;
        modCount++;
        for (int index = tab.length; --index >= 0; )
            tab[index] = null;  //將數(shù)組中的引用全部置為null
        count = 0;
    }

6.2 contains() 和 containsValue()

contains() 和 containsValue() 的作用都是判斷Hashtable是否包含“值(value)”。

    public synchronized boolean contains(Object value) {
        // Hashtable中“鍵值對”的value不能是null,
        // 若是null的話,拋出異常!
        if (value == null) {
            throw new NullPointerException();
        }

        Entry<?,?> tab[] = table;
        // 從后向前遍歷table數(shù)組中的元素(Entry)
        // 對于每個Entry(單向鏈表),逐個遍歷,判斷節(jié)點(diǎn)的值是否等于value
        for (int i = tab.length ; i-- > 0 ;) {
            for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
                if (e.value.equals(value)) {
                    return true;
                }
            }
        }
        return false;
    }
    public boolean containsValue(Object value) {
        return contains(value);
    }

6.3 containsKey()

containsKey() 的作用是判斷Hashtable是否包含key。

    public synchronized boolean containsKey(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        // 計算索引值,
        // % tab.length 的目的是防止數(shù)據(jù)越界
        int index = (hash & 0x7FFFFFFF) % tab.length;
        // 找到“key對應(yīng)的Entry(鏈表)”,然后在鏈表中找出“哈希值”和“鍵值”與key都相等的元素
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return true;
            }
        }
        return false;
    }

6.4 elements()

elements() 的作用是返回“所有value”的枚舉對象。

    public synchronized Enumeration<V> elements() {
        return this.<V>getEnumeration(VALUES);
    }
    // 獲取Hashtable的枚舉類對象
    private <T> Enumeration<T> getEnumeration(int type) {
        if (count == 0) {
            return Collections.emptyEnumeration();
        } else {
            return new Enumerator<>(type, false);
        }
    }

7、put()和get()操作

7.1 put()操作

put() 的作用是對外提供接口,讓Hashtable對象可以通過put()將“key-value”添加到Hashtable中。

    public synchronized V put(K key, V value) {
        // Hashtable中不能插入value為null的元素!?。?
        if (value == null) {
            throw new NullPointerException();
        }

        // 若“Hashtable中已存在鍵為key的鍵值對”,
        // 則用“新的value”替換“舊的value”
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        //計算key的索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        //添加Entry
        addEntry(hash, key, value, index);
        return null;
    }
    private void addEntry(int hash, K key, V value, int index) {
        //將“修改統(tǒng)計數(shù)”+1
        modCount++;

        Entry<?,?> tab[] = table;
        //若“Hashtable實際容量” > “閾值”(閾值=總的容量 * 加載因子)
        //則調(diào)整Hashtable的大小
        if (count >= threshold) {
            // Rehash the table if the threshold is exceeded
            //
            rehash();

            tab = table;
            hash = key.hashCode();
            index = (hash & 0x7FFFFFFF) % tab.length;
        }

        // Creates the new entry.
        //將“Hashtable中index”位置的Entry(鏈表)保存到e中
        @SuppressWarnings("unchecked")
        Entry<K,V> e = (Entry<K,V>) tab[index];
        //采用 “頭插法”
        //創(chuàng)建“新的Entry節(jié)點(diǎn)”,并將“新的Entry”插入“Hashtable的index位置”,
        //并設(shè)置e為“新的Entry”的下一個元素(即“新Entry”為鏈表表頭)。
        tab[index] = new Entry<>(hash, key, value, e);
        //將“Hashtable的實際容量”+1
        count++;
    }

7.2 get()操作

get() 的作用就是獲取key對應(yīng)的value,沒有的話返回null。

    public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        //key的hash值
        int hash = key.hashCode();  
        //計算索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        //找到“key對應(yīng)的Entry(鏈表)”,然后在鏈表中找出“哈希值”和“鍵值”與key都相等的元素
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }

8、rehash()

rehash()函數(shù)負(fù)責(zé)hashtable的擴(kuò)容。

    protected void rehash() {
        int oldCapacity = table.length;
        //擴(kuò)容前的map
        Entry<?,?>[] oldMap = table;

        // overflow-conscious code
        ////新容量 = 舊容量 * 2 + 1  
        int newCapacity = (oldCapacity << 1) + 1;
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            if (oldCapacity == MAX_ARRAY_SIZE)
                // Keep running with MAX_ARRAY_SIZE buckets
                return;
            newCapacity = MAX_ARRAY_SIZE;
        }
        //創(chuàng)建新的數(shù)組
        Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

        modCount++;
        //更新 新的 擴(kuò)容閾值
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        table = newMap;

        //遍歷舊的數(shù)組,將所有的鍵值對Entry移動到新數(shù)組中
        //注意,移動的是對象的引用
        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
                Entry<K,V> e = old;
                old = old.next;

                //計算在新數(shù)組中的索引
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                //采用“頭插法”
                e.next = (Entry<K,V>)newMap[index];
                newMap[index] = e;
            }
        }
    }

9、remove()

remove() 的作用就是刪除Hashtable中鍵為key的元素。

    public synchronized V remove(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        //計算索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> e = (Entry<K,V>)tab[index];
        // 找到“key對應(yīng)的Entry(鏈表)”
        // 然后在鏈表中找出要刪除的節(jié)點(diǎn),并刪除該節(jié)點(diǎn)。
        for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                modCount++;
                if (prev != null) {
                    //鏈表刪除節(jié)點(diǎn)的方式
                    prev.next = e.next;
                } else {
                    tab[index] = e.next;
                }
                count--;
                V oldValue = e.value;
                //將value引用置為null,回收value對象
                e.value = null;
                return oldValue;
            }
        }
        return null;
    }

到此這篇關(guān)于Java中的Hashtable源碼詳細(xì)解析的文章就介紹到這了,更多相關(guān)Hashtable源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot使用Prometheus采集自定義指標(biāo)數(shù)據(jù)的方法詳解

    SpringBoot使用Prometheus采集自定義指標(biāo)數(shù)據(jù)的方法詳解

    隨著微服務(wù)在生產(chǎn)環(huán)境大規(guī)模部署和應(yīng)用,隨之而來也帶來了新的問題,其中比較關(guān)鍵的就是關(guān)于微服務(wù)的運(yùn)維和監(jiān)控,本文將結(jié)合微服務(wù)運(yùn)維監(jiān)控中的指標(biāo)監(jiān)控進(jìn)行詳細(xì)的說明,需要的朋友可以參考下
    2024-07-07
  • IDEA搭建dubbo項目的過程及存在的問題

    IDEA搭建dubbo項目的過程及存在的問題

    這篇文章主要介紹了IDEA搭建dubbo項目及存在的問題小結(jié),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • java連接MySQl數(shù)據(jù)庫實例代碼

    java連接MySQl數(shù)據(jù)庫實例代碼

    這篇文章介紹了java連接MySQl數(shù)據(jù)庫實例代碼,有需要的朋友可以參考一下
    2013-10-10
  • SpringBoot?隱式參數(shù)注入詳解告別重復(fù)代碼,讓?Controller?更優(yōu)雅

    SpringBoot?隱式參數(shù)注入詳解告別重復(fù)代碼,讓?Controller?更優(yōu)雅

    本文介紹了使用SpringBoot的HandlerMethodArgumentResolver實現(xiàn)隱式參數(shù)注入的技巧,通過自定義注解和解析器,可以簡化Controller中的重復(fù)參數(shù)處理邏輯,提升代碼的可維護(hù)性和可讀性,感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • Mybatis 中的sql批量修改方法實現(xiàn)

    Mybatis 中的sql批量修改方法實現(xiàn)

    在項目中遇到需要批量更新的功能,原本想的是在Java中用循環(huán)訪問數(shù)據(jù)庫去更新,但是心里總覺得這樣做會不會太頻繁了,太耗費(fèi)資源了,效率也很低,查了下mybatis的批量操作,原來確實有<foreach>標(biāo)簽可以做到,下面通過本文給大家介紹下
    2017-01-01
  • Java解析JSON的六種方案

    Java解析JSON的六種方案

    這篇文章介紹了 6 種 JSON 解析方案,包括 Jackson、Gson、FastJSON、JsonPath、、手動解析,分別闡述了它們的功能特點(diǎn)、代碼示例、高級功能、優(yōu)缺點(diǎn)及適用場景,感興趣的小伙伴跟著小編一起來看看吧
    2025-01-01
  • Java并發(fā)編程-volatile可見性詳解

    Java并發(fā)編程-volatile可見性詳解

    這篇文章主要介紹了Java并發(fā)編程-volatile可見性詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 解決Spring Security 用戶帳號已被鎖定問題

    解決Spring Security 用戶帳號已被鎖定問題

    這篇文章主要介紹了解決Spring Security 用戶帳號已被鎖定問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • 從dubbo源碼分析qos-server端口沖突問題及解決

    從dubbo源碼分析qos-server端口沖突問題及解決

    這篇文章主要介紹了從dubbo源碼分析qos-server端口沖突問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • SpringMVC框架實現(xiàn)上傳圖片的示例代碼

    SpringMVC框架實現(xiàn)上傳圖片的示例代碼

    本篇文章主要介紹了SpringMVC框架實現(xiàn)上傳圖片的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09

最新評論

肃北| 广河县| 丰原市| 昭觉县| 景宁| 离岛区| 荥经县| 益阳市| 津南区| 江川县| 富锦市| 当雄县| 成武县| 建阳市| 堆龙德庆县| 长葛市| 吉木萨尔县| 常德市| 金门县| 安仁县| 聂拉木县| 安远县| 大埔县| 平利县| 化德县| 莱阳市| 沙坪坝区| 嘉义县| 高雄市| 武川县| 密山市| 滨海县| 渑池县| 万安县| 长白| 伽师县| 喀喇沁旗| 土默特左旗| 合江县| 双桥区| 沙洋县|