日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java --HashTable学习

發布時間:2024/4/14 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java --HashTable学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?今天在家無事,閑來看看JDK源碼,就從HashTable看起了.

?

鍵值都不能為空。
為了能從hashtable中存儲或者獲取值,作為key的對象必須實現hashCode和equals方法。
一個hashtable實例有兩個參數會影響它的效率:
?? 1、initial Capacity? (初始容量) 默認11
?? 2、load facotr (加載因子):是對哈希表在其容量自動增加之前可以達到多滿的一個尺度 默認0.75f
二、變量

(1)Entry[] table:the hash table data
(2)int count:the total number of entries in the hash table.
(3)threshold: the table is rehashed when its size exceeds this threshold.
? threshold=(int)(capacity * loadFactor).
(4)float loadFactor
(5)int modCount=0 :The mumber of times this Hashtable has been structurally modified.


三、方法


(1)構造方法中:
? 初始化initialCapacity
? 初始化loadFactor
? 初始化table=new Entry[initialCapacity]
? 初始化 threshold=(int)(capacity * loadFactor).


(2) public synchronized int size():返回count的值


(3) public synchronized boolean isEmpty() :count是0返回true,否則返回false.


?(4)
?

public synchronized boolean contains(Object value) {if (value == null) {throw new NullPointerException();}//數組,數組中的每一個元素又是一個單向鏈表(Entry:HashTable的內部類)Entry tab[] = table;for (int i = tab.length ; i-- > 0 ;) {for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {if (e.value.equals(value)) {return true;}}}return false;}

?

(5)第一步:得到當前key的hashCode
???? 第二步:通過hashCode得到在數組中的位置index
???? 第三步:根據index得到單向鏈表,從表頭開始查找,是否存在當前元素。

public synchronized V get(Object key) {Entry tab[] = table;//得到hash值,通過hash值找到在數據中的位置,再在對應的單向鏈表中對應的值。int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {return e.value;}}return null;}

?
(6)增加數組的容量,重新計算hashCode,重新進行存儲,大致分為以下幾步:
? 第一步:增加容量至:oldCapacity * 2 + 1
? 第二步:循環數組,循環每個數組元素對應的單向鏈表,從頭開始,重新計算hashCode,重新進行存儲,

protected void rehash() {int oldCapacity = table.length;Entry[] oldMap = table;int newCapacity = oldCapacity * 2 + 1;Entry[] newMap = new Entry[newCapacity];modCount++;threshold = (int)(newCapacity * loadFactor);table = newMap;for (int i = oldCapacity ; i-- > 0 ;) {for (Entry<K,V> old = oldMap[i] ; old != null ; ) {Entry<K,V> e = old;old = old.next;int index = (e.hash & 0x7FFFFFFF) % newCapacity;e.next = newMap[index];newMap[index] = e;}}}

?
(7) put方法,大致分為三步:
? 第一步:確保value不為空
? 第二步:循環數據,進一步循環鏈表,確保此key在當前hashTable中不存在,如果存在,則更換為新值。
? 第三步:modCount+1,如果當前的count >= threshold,則調用rehash()方法擴充數據容量,重新計算hashCode,重新進行存儲。
? 第四步:在單向鏈表的表頭插入當前entry.
?

public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {V old = e.value;e.value = value;return old;}}modCount++;if (count >= threshold) {// Rehash the table if the threshold is exceededrehash();tab = table;index = (hash & 0x7FFFFFFF) % tab.length;} // Creates the new entry.Entry<K,V> e = tab[index];tab[index] = new Entry<K,V>(hash, key, value, e);count++;return null;}

?

總結:1、hashTable是線程安全的,鍵值不能為空。
????? 2、第一層存儲結構是一個數組,數組中的每個元素又是一個單向鏈表。
????? 3、插入時,通過key的hashCode得到數組中存儲位置,在單向鏈表的表頭插入。
????? 4、插入時要檢查當前數據中的元素個數,是否大于等于threshold,如果大于等于threshold,則會調用rehash()方法,建立一個新的數組,其大小為oldCapacity * 2 + 1,
然后把舊的數組中的每個元素取出來,重新計算hashCode、在數組中的位置、在鏈表中的位置。
????? 5、因為threshold=初始容量*加載因子,所以rehash方法的調用與初始容量、加載因子有很大的關系,而rehash方法是hashtable中最費時間的方法,這就是為什么都說

hashtable實例的初始容量、加載因子最影響他的效率。
????? 6、默認加載因子(0.75)在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查找某個條目的時間。
????? 7、初始容量主要控制空間消耗與執行 rehash 操作所需要的時間損耗之間的平衡。如果初始容量大于 Hashtable 所包含的最大條目數除以加載因子,即最大條目<初始容量

*加載因子,則永遠 不會發生 rehash 操作。但是,將初始容量設置太高可能會浪費空間。

總結

以上是生活随笔為你收集整理的java --HashTable学习的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。