摘要:數據結構小白科普是和中常用的一個容器,采用了數組鏈表的結構來存儲數據新增紅黑樹,當鏈表長度大于以后,鏈表會進化成紅黑樹。下面具體分析的實現思路。
Android 數據結構 java 小白科普
HashMap是java和Android中常用的一個容器,采用了數組+鏈表的結構來存儲數據(PS:jdk1.8新增紅黑樹,當鏈表長度大于8以后,鏈表會進化成紅黑樹)。下面具體分析HashMap的實現思路。
1 為什么要用鏈表很多人疑惑,實現HashMap直接用數組不就可以了嗎,通過hash函數計算出key對應的數組的下標,value直接存進去。為什么會用鏈表呢?
問題的關鍵就出在hash函數身上,因為到現在為止還沒有出現一種一個不同的key對應的hash值都不一樣的函數,(包括MD5,SHA等算法),假如a,b兩個key通過hash函數得到的數組下標都是1,a已經存進數組下標為1的位置,b該怎么存儲呢?把a對應的value刪了,替換成b對應的value?這種作法顯然是不可取的。所以在HashMap中引入了鏈表,還是a,b兩個key,存儲a的時候,我們先判斷下數組下標為1的位置是否有數據,如果沒有直接插入數組中,這時候a對應的value插入到了數組中,這時候我們來存儲b,我們發現下標為1的位置已經存了數據,我們用a.next來指向b,形成一個鏈表。以此類推。
public V put(K key, V value) { //hash()散列函數,主要作用通過一系列計算,得出應存在數組的下標 return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node2 get方法[] tab; Node p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) //擴容數據搬遷 n = (tab = resize()).length; //查看對應下標是否有數據,沒有數據直接插入數據 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node e; K k; //key相等 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; //進化成紅黑樹之后 else if (p instanceof TreeNode) e = ((TreeNode )p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { //判斷是不是鏈表最后一個節點 if ((e = p.next) == null) { //發現是最后一個節點的話,添加在隊尾 p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } //key相等 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } //重新賦值 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
public V get(Object key) { Node3 總結e; return (e = getNode(hash(key), key)) == null ? null : e.value; } final Node getNode(int hash, Object key) { Node [] tab; Node first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) {//取出數組中對應下標數據 //key相同 hash相同 數組中的對象就是我們要找的 if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode )first).getTreeNode(hash, key); do { //循環遍歷 找到key相同的對象 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
HashMap通過數組加鏈表的方式,實現了時間復雜度為O(1)的快速插入,查詢等操作,在平時使用中我們還可以通過指定數組大小來進一步加快它的性能。
文章中只是寫了大概的思路,有不對的還請見諒!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72544.html
摘要:任務名稱響應式砸蛋頁面任務背景前輩方方啊最近項目也沒什么事情你看這個砸蛋頁面不是很好看要不你做一個響應式砸蛋頁面吧系統鄭方方接下前輩的任務鄭方方自動解析任務步驟任務響應式砸蛋頁面與入門閱讀秘籍響應式布局制作層搭配搭配控制器完成任務人物背 任務名稱:響應式砸蛋頁面 任務背景 前輩:方方啊,最近項目也沒什么事情,你看這個砸蛋頁面不是很好看,要不你做一個響應式砸蛋頁面吧? 系統:鄭方方接下前...
摘要:任務名稱響應式砸蛋頁面任務背景前輩方方啊最近項目也沒什么事情你看這個砸蛋頁面不是很好看要不你做一個響應式砸蛋頁面吧系統鄭方方接下前輩的任務鄭方方自動解析任務步驟任務響應式砸蛋頁面與入門閱讀秘籍響應式布局制作層搭配搭配控制器完成任務人物背 任務名稱:響應式砸蛋頁面 任務背景 前輩:方方啊,最近項目也沒什么事情,你看這個砸蛋頁面不是很好看,要不你做一個響應式砸蛋頁面吧? 系統:鄭方方接下前...
摘要:任務名稱響應式砸蛋頁面任務背景前輩方方啊最近項目也沒什么事情你看這個砸蛋頁面不是很好看要不你做一個響應式砸蛋頁面吧系統鄭方方接下前輩的任務鄭方方自動解析任務步驟任務響應式砸蛋頁面與入門閱讀秘籍響應式布局制作層搭配搭配控制器完成任務人物背 任務名稱:響應式砸蛋頁面 任務背景 前輩:方方啊,最近項目也沒什么事情,你看這個砸蛋頁面不是很好看,要不你做一個響應式砸蛋頁面吧? 系統:鄭方方接下前...
閱讀 674·2021-11-24 09:39
閱讀 2342·2021-11-22 13:54
閱讀 2210·2021-09-23 11:46
閱讀 3256·2019-08-30 15:55
閱讀 2691·2019-08-30 15:54
閱讀 2415·2019-08-30 14:18
閱讀 1554·2019-08-29 14:15
閱讀 2745·2019-08-29 13:49