HashMap 基礎原理以及原始碼解讀
第一次寫部落格,有理解或者表述不對的地方望博友指出,一起交流,一起進步。
基礎的資料結構,大家都不陌生, 基於 陣列、連結串列之類 大家一定不陌生,今天我們們聊一聊他們的具體儲存原理和效率。
陣列 : 佔用空間大,故空間複雜度大 ,但是陣列的二分法查詢時間複雜度小 ,查詢容易,增加刪除困難
連結串列 : 連結串列儲存空間離散, 佔用記憶體比較寬鬆,故空間複雜度很小,但時間複雜度較大 , 所以查詢困難 ,增加刪除容易
以上兩種資料結構效率均有所不如人意,雜湊表就滿足了查詢容易,和增刪容易
關於雜湊表,最常用的實現就是拉鍊法-->也就是連結串列的陣列
雜湊表本身由陣列+連結串列 組成,一個長度為16的陣列中,每個元素儲存的是一個連結串列的頭結點。那麼這些元素是按照什麼樣的規則儲存到陣列中呢。一般情況是通過hash(key)%len獲得,也就是元素的key的雜湊值對陣列長度取模得到。
HashMap是一個線性的陣列實現的,所以可以理解為其儲存資料的容器就是一個線性陣列。這可能讓我們很不解,一個線性的陣列怎麼實現按鍵值對來存取資料呢?這裡HashMap有做一些處理。
看下HashMap的原始碼 jdk1.8可以發現 HashMap 的 put方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i;//n 陣列長度 tab為陣列 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null)// 如果雜湊值對應的值不存在,在陣列對應位置新建陣列 確定陣列index tab[i] = newNode(hash, key, value, null); else {//否則確定陣列index,對應位置新建連結串列 Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)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; } 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)//如果size超過threshold,則擴充table大小。再雜湊 resize(); afterNodeInsertion(evict); return null; } HashMap 的get方法原始碼部分(查詢)
final Node<K,V> getNode(int hash, Object key) {//檢查對應的雜湊值是否一樣,確定陣列index 再根據key找到對應的連結串列的位置 返回 Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { 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<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }參考答案 http://blog.csdn.net/vking_wang/article/details/14166593
相關文章
- HashMap原始碼解讀HashMap原始碼
- Java基礎——HashMap原始碼分析JavaHashMap原始碼
- java基礎:HashMap — 原始碼分析JavaHashMap原始碼
- HashMap原始碼個人解讀HashMap原始碼
- HashMap 原始碼閱讀HashMap原始碼
- HashMap原始碼閱讀HashMap原始碼
- 原始碼閱讀-HashMap原始碼HashMap
- Java-HashMap中put原始碼解讀JavaHashMap原始碼
- HashMap原始碼解析和設計解讀HashMap原始碼
- java基礎型別原始碼解析之HashMapJava型別原始碼HashMap
- HashMap原始碼詳解HashMap原始碼
- java 8 HashMap 原始碼閱讀JavaHashMap原始碼
- 閱讀原始碼,HashMap回顧原始碼HashMap
- HashMap 實現原理與原始碼分析HashMap原始碼
- 原始碼的魅力 – HashMap 的工作原理原始碼HashMap
- HashMap實現原理及原始碼分析HashMap原始碼
- Spring:原始碼解讀Spring IOC原理Spring原始碼
- 【JDK原始碼分析】淺談HashMap的原理JDK原始碼HashMap
- 從原始碼解讀Category實現原理原始碼Go
- CyberRT_recorder原始碼解讀以及record解析原始碼
- 詳解HashMap原始碼解析(上)HashMap原始碼
- 詳解HashMap原始碼解析(下)HashMap原始碼
- HashMap原始碼分析(二):看完徹底瞭解HashMapHashMap原始碼
- Vue 原始碼解讀(3)—— 響應式原理Vue原始碼
- 從koa-session原始碼解讀session原理Session原始碼
- JDK原始碼閱讀(4):HashMap類閱讀筆記JDK原始碼HashMap筆記
- 【原始碼解讀(二)】EFCORE原始碼解讀之查詢都做了什麼以及如何自定義批次插入原始碼
- vux之x-input使用以及原始碼解讀UX原始碼
- Django 原始碼閱讀筆記(基礎檢視)Django原始碼筆記
- 閱讀原始碼,通過LinkedList回顧基礎原始碼
- PostgreSQL 原始碼解讀(165)- 查詢#85(基礎知識-詞法分析)SQL原始碼詞法分析
- 原始碼分析系列1:HashMap原始碼分析(基於JDK1.8)原始碼HashMapJDK
- HashMap原始碼剖析HashMap原始碼
- HashMap 原始碼分析HashMap原始碼
- 原始碼分析——HashMap原始碼HashMap
- HashMap原始碼分析HashMap原始碼
- HashMap原始碼整理HashMap原始碼
- Java-基礎-HashMapJavaHashMap
- ADT基礎(三)—— HashMapHashMap