HashMap 源码
生活随笔
收集整理的這篇文章主要介紹了
HashMap 源码
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.8 閾值
resize()函數(shù) threshold = newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);? 16*0.75 = 12?
JDK1.7 put()
public V put(K key, V value) {if (table == EMPTY_TABLE) {//初始化大小 根據(jù)要?jiǎng)?chuàng)建的數(shù)組大小計(jì)算出2次冪最接近的數(shù)字inflateTable(threshold);}if (key == null)//key為空的話直接放到數(shù)組[0]return putForNullKey(value);int hash = hash(key);//計(jì)算hash值 高位右移 使得高位參與hash運(yùn)算 優(yōu)化散列效果int i = indexFor(hash, table.length);//根據(jù)hash值和數(shù)組長(zhǎng)度算出腳標(biāo) h & (length-1);//遍歷數(shù)組[i]為頭結(jié)點(diǎn)的鏈表for (Entry<K,V> e = table[i]; e != null; e = e.next) {Object k;//找到key相同的元素的話 覆蓋value 并且返回被覆蓋的valueif (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}modCount++;//沒找到節(jié)點(diǎn)的話 添加新節(jié)點(diǎn)addEntry(hash, key, value, i);return null;}JDK1.7擴(kuò)容 轉(zhuǎn)移數(shù)據(jù)
/*** Transfers all entries from current table to newTable.*/void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;//遍歷數(shù)組for (Entry<K,V> e : table) {//遍歷鏈表while(null != e) {//保存next元素Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 : hash(e.key);}int i = indexFor(e.hash, newCapacity);//頭插法 將新元素插入到新的table 并把新table原來的元素插入到后面e.next = newTable[i];//新元素作為數(shù)組的頭結(jié)點(diǎn)newTable[i] = e;e = next;}}}JDK1.8 put()
/*** Implements Map.put and related methods** @param hash hash for key* @param key the key* @param value the value to put* @param onlyIfAbsent if true, don't change existing value* @param evict if false, the table is in creation mode.* @return previous value, or null if none*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)//創(chuàng)建數(shù)組n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)//當(dāng)前數(shù)組位置為空直接創(chuàng)建節(jié)點(diǎn)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//數(shù)組第一個(gè)元素如果hash和key一樣的話直接覆蓋valueelse if (p instanceof TreeNode)//如果第一個(gè)節(jié)點(diǎn)為樹節(jié)點(diǎn)的話 插入樹節(jié)點(diǎn)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//不是樹節(jié)點(diǎn)的話遍歷鏈表for (int binCount = 0; ; ++binCount) {//如果遍歷到鏈表尾部的話 插到最后一個(gè)節(jié)點(diǎn)if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);//深度達(dá)到8時(shí)候轉(zhuǎn)化成紅黑樹if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);--------final void treeifyBin(Node<K,V>[] tab, int hash) {--------int n, index; Node<K,V> e;--------數(shù)組長(zhǎng)度小于64的話會(huì)進(jìn)行擴(kuò)容而不是樹化 而是進(jìn)行擴(kuò)容--------if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)-------resize();break;}//發(fā)現(xiàn)hash和key相同的話 退出循環(huán)if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;//指針指向下一個(gè)節(jié)點(diǎn)p = e;}}//找到了key相等的直節(jié)點(diǎn) 覆蓋新值 返回舊值if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)//大于閾值 擴(kuò)容resize();afterNodeInsertion(evict);return null;}https://www.bilibili.com/video/av79122849
https://www.bilibili.com/video/av82235643
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎(jiǎng)!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的HashMap 源码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 加载NMGameX.dll时出错?
- 下一篇: linux 物理内存用完了_调整linu