jdk1.8中HashMap是如何維護EntrySet的
如果大家分析過hashmap的原始碼,就會發現HashMap維護EntrySet的方式是比較特別的。有的人會疑問,jdk1.8中HashMap到底是如何維護EntrySet的。一般來說,我們實現EntrySet就是在put值的時候將其順便加到EntrySet即可。但是jdk1.8中並沒有這樣做。
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;
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;
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)
resize();
afterNodeInsertion(evict);
return null;
}
可以看到,這段程式碼中並沒有一絲維護EntrySet的跡象。
那麼平時我們遍歷Map的時候獲取EntrySet是怎麼來的呢?
我們可以看看EntrySet方法的原始碼:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
可以看到,就直接返回了一個entrySet,那麼這個entrySet是什麼呢?
transient Set<Map.Entry<K,V>> entrySet;
我們不難看到,整個過程中,就直接返回了entrySet,我們在put 的時候也看不到jdk將put的元素加入到entrySet中,那我們遍歷的時候元素哪裡來?
我們可以看到,雖然是返回的entrySet,但是事實上你在輸出(System.out.println)entrySet的時候,是會呼叫toString()的,我們看看toString方法的原始碼:
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
可以看到,原來jdk使用了懶載入的方式。其中iterator就會獲取hashMap裡面的元素了。
相關推薦
jdk1.8中HashMap是如何維護EntrySet的
如果大家分析過hashmap的原始碼,就會發現HashMap維護EntrySet的方式是比較特別的。有的人會疑問,jdk1.8中HashMap到底是如何維護EntrySet的。一般來說,我們實現EntrySet就是在put值的時候將其順便加到EntrySet即可
JDK1.8中HashMap實現
替換 應該 初始化 第一個元素 擴容 實現 1.8 put 相同 JDK1.8中的HashMap實現跟JDK1.7中的實現有很大差別。下面分析JDK1.8中的實現,主要看put和get方法。 構造方法的時候並沒有初始化,而是在第一次put的時候初始化 put
1.jdk1.8中hashMap的原理,hash衝突如何解決
一:hashMap的工作原理 HashMap是基於鏈地址法的原理,使用put(key, value)儲存物件到HashMap中,使用get(key)從HashMap中獲取物件。 當我們給put()方法傳遞鍵和值時,我們先對鍵呼叫hashCode
通俗易懂的JDK1.8中HashMap原始碼分析(歡迎探討指正)+ 典型面試題
面試題在最下面 說到HashMap之前,閱讀ArrayList與LinkedList的原始碼後做個總結 ArrayList 底層是陣列,查詢效率高,增刪效率低 LinkedList底層是雙鏈表,查詢效率低,增刪效率高 這裡只是總結看完原始碼後對hashm
JAVA筆記 —— JDK1.8中 HashMap 的變化
HashMap(1.8) 1、資料結構的變化:紅黑樹 JDK1.8之前,HashMap的資料結構:陣列 + 連結串列(單鏈表) JDK1.8之後,HashMap的資料結構:陣列 + 連結串列 + 紅黑樹 JDK1.8之前,HashMap採用陣列+連結串
JDK1.7和1.8中HashMap與ConcurrentHashMap總結比較
談到HashMap和ConcurrentHashMap,必然會聯想到一些其他集合結構,比如HashTable,Vector等,先理一下他們的區別吧。其實HashTable和Vector已經被廢棄了,HashTable和Vector以及ConcurrentHashMap都是執行緒安全的同步結構,區別是
JDK1.8 中的hashmap和concurrentHashMap
hashmap 在JDK1.6中,HashMap採用Node陣列+連結串列實現,即使用連結串列處理衝突,同一hash值的連結串列都儲存在一個連結串列裡。但是當位於一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查詢的效率較低。而JDK1.8中
HashMap 在JDK1.8中的實現
摘要HashMap是Java程式設計師使用頻率最高的用於對映(鍵值對)處理的資料型別。隨著JDK(Java Developmet Kit)版本的更新,JDK1.8對HashMap底層的實現進行了優化,例如引入紅黑樹的資料結構和擴容的優化等。本文結合JDK1.7和JDK1.8的區別,深入探討HashMap的結構
JDK1.7中HashMap死環問題及JDK1.8中對HashMap的優化原始碼詳解
一、JDK1.7中HashMap擴容死鎖問題 我們首先來看一下JDK1.7中put方法的原始碼 我們開啟addEntry方法如下,它會判斷陣列當前容量是否已經超過的閾值,例如假設當前的陣列容量是16,載入因子為0.75,即超過了12,並且剛好要插入的索引處有元素,這時候就需要進行擴容操作,可以看到resi
jdk1.8中接口可以寫默認方法
wheel void JD PE 靜態 調用 默認 sta default interface Vehicle { default void print(){ System.out.println("我是一輛車!"); } stat
Java7、8中HashMap和ConcurrentHashMap原始碼閱讀
首先來看下HashMap的類繼承結構: public class HashMap extends AbstractMap<K,V> impement Map<K,V>,Coloneable,Serializable{ } 可以看出HashMap實現了Map介面。其裡面的方法都是
Java7、8中HashMap和ConcurrentHashMap源碼閱讀
動態擴容 nal das pub end flat 數據 算數 ext 首先來看下HashMap的類繼承結構: public class HashMap extends AbstractMap<K,V> impement Map<K,V>,Colon
java 7/ 8 中 HashMap 及 concurrentHashMap
前言: HashMap 不支援併發操作,而concurrentHashMap 支援併發操作,本文簡單介紹Java 7 、Java8 中HashMap 及 concurrentHashMap 底層實現。 1、Java 7 中 HashMap
JDK1.8中TreeMap原始碼解析——紅黑樹刪除
在看本文之前建議先看一下二叉樹的刪除過程,這裡有一篇文章寫得不錯,可以看一下 1、後繼節點 在看原始碼之前,先說說紅黑樹尋找 待刪除節點t 的 後繼節點 的過程: 如果待刪除節點t有右節點,那麼後繼節點為該節點右子樹中最左的節點,也就是右子樹中值最小的節
Java7/8 中 HashMap 和 ConcurrentHashMap的對比和分析
網上關於 HashMap 和 ConcurrentHashMap 的文章確實不少,不過缺斤少兩的文章比較多,所以才想自己也寫一篇,把細節說清楚說透,尤其像 Java8 中的 ConcurrentHashMap,大部分文章都說不清楚。終歸是希望能降低大家學習的成本,不希望大家到處找各種不是很靠譜的文章,看完一篇
jdk1.8中computeIfAbsent方法用法
computeIfAbsent(K key, Function《? super K, ? extends V> mappingFunction) computeIfAbsent的方法有兩個引數 第一個是所選map的key,第二個是需要做的操作。這個方法當key值不存在
Java 8中HashMap和LinkedHashMap如何解決衝突
什麼時候會產生衝突?? HashMap中呼叫hashCode()方法來計算hashCode。 由於在Java中兩個不同的物件可能有一樣的hashCode,所以不同的鍵可能有一樣hashCode,從而導致衝突的產生。 解決: 在Java 8 之前,HashMap和其他基於map
ConcurrentHashMap JDK1.8中結構原理及原始碼分析
注:本文根據網路和部分書籍整理基於JDK1.7書寫,如有雷同敬請諒解 歡迎指正文中的錯誤之處。 資料結構 ConcurrentHashMap 1.8 拋棄了Segment分段鎖機制,採用Node + CAS + Synchronized來保證併發安全進行實現
在JDK1.8中介面和抽象類
public abstract class Person { // 1,可以定義成員變數 //2, 可以是任意許可權修飾符 private int a = 1; protected int b =1; public int c = 1; //3,
【轉】Java 8中HashMap和LinkedHashMap如何解決衝突
原文來自一個java大牛的部落格 原文地址http://javarevisited.blogspot.jp/2016/01/how-does-java-hashmap-or-linkedhahsmap-handles.html 部落格講解了Java 8中HashMap和LinkedH