轉載
在hashtable和hashmap是java里面常見的容器類,
是Java.uitl包下面的類,
那么Hashtable和Hashmap是怎么實現hash鍵值對配對的呢,我們看看jdk里面的源碼,分析下Hashtable的構造方法,put(K, V)加入方法和get(Object)方法就大概明白了。
一、Hashtable的構造方法:Hashtable(int initialCapacity, float loadFactor)
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)(initialCapacity * loadFactor);
}
這個里面米內有什么好說的,要注意的是table一個是實體數組,輸入的initialCapacity表示這個數組的大小,而threshold 是一個int值,其中loadFactor默認是0.75,就是說明,當table里面的值到75%的閥值后,快要填滿數組了,就會自動雙倍擴大數字容 量。
而Entry<K,V> 來自與
PRivate static class Entry<K,V> implements Map.Entry<K,V> {
int hash;
K key;
V value;
Entry<K,V> next;
是一個單項鏈表,
上圖就是Hashtable的表,
二、put(K, V)加入方法
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (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 ld = e.value;
e.value = value;
return old;
}
}modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();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.index,index是鍵值的hashcode和0x7FFFFFFF的&運算,然后根據數組長度求余值。這樣可以定出所在隊列名稱,
2、
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V ld = e.value;
e.value = value;
return old;
}
}
for語句里面是讓e在tab某個隊列名為index單項鏈表里面遍歷,第幾個單項鏈表的定義由index定義,看看該隊列是否已經有同樣的值,如果有,就返回該值。
3、如果沒有,則加入
Entry<K,V> e = tab[index];
tab[index] = new Entry<K,V>(hash, key, value, e);
三、get(Object),獲得
public synchronized V get(Object key) {
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)) {
return e.value;
}
}
return null;
}
這個就很好理解了 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;
}
}
在該隊里面遍歷,根據hash值獲得具體值。
總結下,一個是根據index確定隊列,在由hash值獲得具體元素值。
看完了hashtable, 我們在來看看hashMap
hashMap可以算作是hashtable的升級版本, 最早從1.2開始有的.
但是, 兩者之間最主要的不同有兩點.
1. hashMap的讀寫是unsynchronized, 在多線程的環境中要注意使用
而hashtable是synchronized
這兩者的不同是通過在讀寫方法上加synchronized關鍵字來實現的.
第二個不同是hashMap可以放空值, 而hashtable就會報錯.
新聞熱點
疑難解答