亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

1、簡(jiǎn)介

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

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

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

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

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

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

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

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

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

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

Hashtable中的key-value都是存儲(chǔ)在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; //鏈表中下一個(gè)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()方法,判斷兩個(gè)Entry是否相等。
        // 若兩個(gè)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對(duì)象的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的主要對(duì)外接口

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中“鍵值對(duì)”的value不能是null,
        // 若是null的話,拋出異常!
        if (value == null) {
            throw new NullPointerException();
        }

        Entry<?,?> tab[] = table;
        // 從后向前遍歷table數(shù)組中的元素(Entry)
        // 對(duì)于每個(gè)Entry(單向鏈表),逐個(gè)遍歷,判斷節(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();
        // 計(jì)算索引值,
        // % tab.length 的目的是防止數(shù)據(jù)越界
        int index = (hash & 0x7FFFFFFF) % tab.length;
        // 找到“key對(duì)應(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”的枚舉對(duì)象。

    public synchronized Enumeration<V> elements() {
        return this.<V>getEnumeration(VALUES);
    }
    // 獲取Hashtable的枚舉類對(duì)象
    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() 的作用是對(duì)外提供接口,讓Hashtable對(duì)象可以通過(guò)put()將“key-value”添加到Hashtable中。

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

        // 若“Hashtable中已存在鍵為key的鍵值對(duì)”,
        // 則用“新的value”替換“舊的value”
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        //計(jì)算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)計(jì)數(shù)”+1
        modCount++;

        Entry<?,?> tab[] = table;
        //若“Hashtable實(shí)際容量” > “閾值”(閾值=總的容量 * 加載因子)
        //則調(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”的下一個(gè)元素(即“新Entry”為鏈表表頭)。
        tab[index] = new Entry<>(hash, key, value, e);
        //將“Hashtable的實(shí)際容量”+1
        count++;
    }

7.2 get()操作

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

    public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        //key的hash值
        int hash = key.hashCode();  
        //計(jì)算索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        //找到“key對(duì)應(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ù)組,將所有的鍵值對(duì)Entry移動(dòng)到新數(shù)組中
        //注意,移動(dòng)的是對(duì)象的引用
        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;

                //計(jì)算在新數(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();
        //計(jì)算索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> e = (Entry<K,V>)tab[index];
        // 找到“key對(duì)應(yīng)的Entry(鏈表)”
        // 然后在鏈表中找出要?jiǎng)h除的節(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對(duì)象
                e.value = null;
                return oldValue;
            }
        }
        return null;
    }

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

相關(guān)文章

  • 淺談使用java解析和生成JSON

    淺談使用java解析和生成JSON

    在www.json.org上公布了很多JAVA下的json構(gòu)造和解析工具,其中g(shù)oogle-gson和org.json比較簡(jiǎn)單,兩者使用上差不多但還是有些區(qū)別。下面我們就來(lái)分別介紹下用他們構(gòu)造和解析Json數(shù)據(jù)的方法示例。
    2015-08-08
  • SpringBoot之@Scheduled注解用法解讀

    SpringBoot之@Scheduled注解用法解讀

    這篇文章主要介紹了SpringBoot之@Scheduled注解用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 利用maven引入第三方j(luò)ar包以及打包

    利用maven引入第三方j(luò)ar包以及打包

    Maven是通過(guò)倉(cāng)庫(kù)對(duì)依賴進(jìn)行管理的,當(dāng)Maven項(xiàng)目需要某個(gè)依賴時(shí),只要其POM中聲明了依賴的坐標(biāo)信息,Maven就會(huì)自動(dòng)從倉(cāng)庫(kù)中去下載該構(gòu)件使用,如何將jar引用到項(xiàng)目,并且能夠讓項(xiàng)目正常調(diào)用該jar包的方法,本篇文章重點(diǎn)針對(duì)于這兩點(diǎn)進(jìn)行講解
    2023-05-05
  • Springboot RestTemplate 簡(jiǎn)單使用解析

    Springboot RestTemplate 簡(jiǎn)單使用解析

    這篇文章主要介紹了Springboot RestTemplate 簡(jiǎn)單使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Spring中校驗(yàn)器(Validator)的深入講解

    Spring中校驗(yàn)器(Validator)的深入講解

    Spring校驗(yàn)器,參數(shù)校驗(yàn)從此簡(jiǎn)單。下面這篇文章主要給大家介紹了關(guān)于Spring中校驗(yàn)器(Validator)的相關(guān)資料,文中通過(guò)示例代碼介紹非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • 使用maven創(chuàng)建普通項(xiàng)目命令行程序詳解

    使用maven創(chuàng)建普通項(xiàng)目命令行程序詳解

    大部分使用maven創(chuàng)建的是web項(xiàng)目,這里使用maven創(chuàng)建一個(gè)命令行程序,目的是讓大家了解maven特點(diǎn)和使用方式,有需要的朋友可以借鑒參考下
    2021-10-10
  • java開發(fā)SSM框架具有rest風(fēng)格的SpringMVC

    java開發(fā)SSM框架具有rest風(fēng)格的SpringMVC

    這篇文章主要介紹了java開發(fā)中如何使SSM框架具有rest風(fēng)格的SpringMVC實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • Java中byte輸出write到文件的實(shí)現(xiàn)方法講解

    Java中byte輸出write到文件的實(shí)現(xiàn)方法講解

    今天小編就為大家分享一篇關(guān)于Java中byte輸出write到文件的實(shí)現(xiàn)方法講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • Spring Data JPA 如何使用QueryDsl查詢并分頁(yè)

    Spring Data JPA 如何使用QueryDsl查詢并分頁(yè)

    這篇文章主要介紹了Spring Data JPA 如何使用QueryDsl查詢并分頁(yè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 解決resultMap映射數(shù)據(jù)錯(cuò)誤的問(wèn)題

    解決resultMap映射數(shù)據(jù)錯(cuò)誤的問(wèn)題

    這篇文章主要介紹了解決resultMap映射數(shù)據(jù)錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評(píng)論