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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

HashMap解析

發(fā)布時(shí)間:2024/9/19 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HashMap解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

HashMap解析

HashMap的兩個(gè)版本

HashMap在JDK7之后發(fā)生了一些改變,所以有兩個(gè)版本:

  • JDK7下的HashMap(數(shù)組+鏈表)
  • JDK8下的HashMap(數(shù)組+鏈表+紅黑樹)

HashMap(java7版本)

結(jié)構(gòu)解析

Java7的版本下的HashMap如下:

HashMap 里面是一個(gè)數(shù)組,然后數(shù)組中每個(gè)元素是一個(gè)單向鏈表。并且HashMap 的數(shù)組是運(yùn)行擴(kuò)容的,也就是說當(dāng)數(shù)組不夠用時(shí),可以通過擴(kuò)容來(lái)擴(kuò)大數(shù)組的容量。HashMap數(shù)組中存儲(chǔ)的是Entry 的實(shí)例。

Entry實(shí)例有一個(gè)key值,一個(gè)value值,一個(gè)hsah值和一個(gè)指針(引用)。Entry實(shí)例就是我們平時(shí)的k-V對(duì)了。

構(gòu)造參數(shù)

capacity:當(dāng)前數(shù)組容量,始終保持 2^n。

loadFactor:負(fù)載因子,默認(rèn)為 0.75。

threshold:擴(kuò)容的閾值,等于 capacity * loadFactor

put過程

源代碼

public V put(K key, V value) {// 當(dāng)插入第一個(gè)元素的時(shí)候,需要先初始化數(shù)組if (table == EMPTY_TABLE) {inflateTable(threshold);}// 如果 key 為 null,將entry放到table[0]中if (key == null)return putForNullKey(value);// 1. 對(duì) key 的 hash 值int hash = hash(key);// 2. 通過key的hash值映射成數(shù)組的下標(biāo)int i = indexFor(hash, table.length);// 3. 遍歷一下對(duì)應(yīng)下標(biāo)處的鏈表,看是否有重復(fù)的 key 已經(jīng)存在,for (Entry<K,V> e = table[i]; e != null; e = e.next) {Object k;// 有,則覆蓋,并put 方法返回舊值if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}modCount++;// 4. 不存在重復(fù)的 key,將此 entry 添加到鏈表中addEntry(hash, key, value, i);return null; }

get過程

通過key計(jì)算hash值

通過值找到數(shù)組下標(biāo)

遍歷數(shù)組下標(biāo)下的鏈表

public V get(Object key) {// key為null遍歷table[0] 處的鏈表if (key == null)return getForNullKey();// 根據(jù)key那entry對(duì)象Entry<K,V> entry = getEntry(key);return null == entry ? null : entry.getValue(); }

HashMap(java8版本)

ava8 對(duì) HashMap 進(jìn)行了一些修改,所以其由 數(shù)組+鏈表+紅黑樹 組成。

結(jié)構(gòu)解析

HashMap (JDK1.8):底層實(shí)現(xiàn)是數(shù)組+鏈表+紅黑樹,當(dāng)鏈表中的元素超過了 8 個(gè)以后,會(huì)將鏈表轉(zhuǎn)換為紅黑樹。

put過程

public V put(K key, V value) {//put方法調(diào)用的是putValreturn putVal(hash(key), key, value, false, true); }//hash:key的hash,key:鍵 value:值 //onlyIfAbsent:放置模式 如果是 true,那么只有在不存在該 key 時(shí)才會(huì)進(jìn)行 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;//初始化數(shù)組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<K,V> e; K k;//判斷是否重復(fù)if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//再判斷是否為紅黑樹節(jié)點(diǎn),是則通過紅黑樹的方式插入else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);//否則跟JDK1.7的鏈表一樣插入else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);//插入新節(jié)點(diǎn)后判斷長(zhǎng)度是否超過8,超過就將鏈表轉(zhuǎn)化為紅黑樹if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) {V oldValue = e.value;//根據(jù)前面的onlyIfAbsent參數(shù)覆蓋掉舊值if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null; }

get過程

public V get(Object key) {Node<K,V> e;return (e = getNode(hash(key), key)) == null ? null : e.value; } final Node<K,V> getNode(int hash, Object 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) {// 判斷第一個(gè)節(jié)點(diǎn)if (first.hash == hash && // always check first node((k = first.key) == key || (key != null && key.equals(k))))return first;if ((e = first.next) != null) {// 判斷是否是紅黑樹,是則通過紅黑樹的方式那節(jié)點(diǎn)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; }

總結(jié)

以上是生活随笔為你收集整理的HashMap解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。