文本要害字:程序設計/java/入門
在Java的世界里,無論類還是各種數據,其結構的處理是整個程序的邏輯以及性能的要害。由于本人接觸了一個有關性能與邏輯同時并存的問題,于是就開始研究這方面的問題。
HashMap可謂JDK的一大實用工具,把各個Object映射起來,實現了“鍵--值”對應的快速存取。但實際里面做了些什么呢?
在這之前,先介紹一下負載因子和容量的屬性。大家都知道其實一個 HashMap 的實際容量就 因子*容量,其默認值是 16×0.75=12; 這個很重要,對效率很一定影響!當存入HashMap的對象超過這個容量時,HashMap 就會重新構造存取表。這就是一個大問題,我后面慢慢介紹,反正,假如你已經知道你大概要存放多少個對象,最好設為該實際容量的能接受的數字。
兩個要害的方法,put和get:
先有這樣一個概念,HashMap是聲明了 Map,Cloneable, Serializable 接口,和繼續了 AbstractMap 類,里面的 Iterator 其實主要都是其內部類HashIterator 和其他幾個 iterator 類實現,當然還有一個很重要的繼續了Map.Entry 的 Entry 內部類,由于大家都有源代碼,大家有愛好可以看看這部分,我主要想說明的是 Entry 內部類。它包含了hash,value,key 和next 這四個屬性,很重要。put的源碼如下
public Object put(Object key, Object value) {
Object k = maskNull(key);
這個就是判定鍵值是否為空,并不很深奧,其實假如為空,它會返回一個static Object 作為鍵值,這就是為什么HashMap答應空鍵值的原因。
int hash = hash(k);
int i = indexFor(hash, table.length);
這連續的兩步就是 HashMap 最牛的地方!研究完我都汗顏了,其中 hash 就是通過 key 這個Object的 hashcode 進行 hash,然后通過 indexFor 獲得在Object table的索引值。
table???不要驚奇,其實HashMap也神不到哪里去,它就是用 table 來放的。最牛的就是用 hash 能正確的返回索引。其中的hash算法,我跟JDK的作者 Doug 聯系過,他建議我看看《The art of programing vol3》可恨的是,我之前就一直在找,我都找不到,他這樣一提,我就更加急了,可惜口袋空空?。。。?/P>
不知道大家有沒有留意 put 其實是一個有返回的方法,它會把相同鍵值的 put 覆蓋掉并返回舊的值!如下方法徹底說明了 HashMap 的結構,其實就是一個表加上在相應位置的Entry的鏈表:
for (Entry e = table[i]; e != null; e = e.next) {
if (e.hash == hash && eq(k, e.key)) {
Object oldvalue = e.value;
e.value = value; //把新的值賦予給對應鍵值。
e.recordaccess(this); //空方法,留待實現
return oldvalue; //返回相同鍵值的對應的舊的值。
}
}
modCount++; //結構性更改的次數
addEntry(hash, k, value, i); //添加新元素,要害所在!
return null; //沒有相同的鍵值返回
}
我們把要害的方法拿出來分析:
void addEntry(int hash, Object key, Object value, int bUCketIndex) {
table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);
因為 hash 的算法有可能令不同的鍵值有相同的hash碼并有相同的table索引,如:key=“33”和key=Object g的hash都是-8901334,那它經過indexfor之后的索引一定都為i,這樣在new的時候這個Entry的next就會指向這個原本的table[i],再有下一個也如此,形成一個鏈表,和put的循環對定e.next獲得舊的值。到這里,HashMap的結構,大家也十分明白了吧?
新聞熱點
疑難解答