首先從一條簡單的語句開始,建立了一個hashmap對象:數組
Map<String,String> hashmap = new HashMap<String,String>(); this
調用hashmap類無參數構造方法,使用默認轉載因子,spa
1 public HashMap() { 2 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 3 }
默認裝載因子只有在構造器不指定的狀況下使用code
1 /** 2 * The load factor used when none specified in constructor. 3 */ 4 static final float DEFAULT_LOAD_FACTOR = 0.75f;
hashmap還有三個重載的構造方法,分別是:對象
有裝載因子入參的構造方法blog
1 public HashMap(int initialCapacity) { 2 this(initialCapacity, DEFAULT_LOAD_FACTOR); 3 }
有初始化容器容量以及裝載因子的構造方法ci
1 public HashMap(int initialCapacity, float loadFactor) { 2 //若是初始容量小於0,則拋出非法初始化容量異常 3 if (initialCapacity < 0) 4 throw new IllegalArgumentException("Illegal initial capacity: " + 5 initialCapacity); 6 //若是初始容量大於最多容量,則容量爲最多容量 7 if (initialCapacity > MAXIMUM_CAPACITY) 8 initialCapacity = MAXIMUM_CAPACITY; 9 //若是裝載因子不大於0或者裝載因子不是數字,則拋出裝載因子非法異常 10 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 11 throw new IllegalArgumentException("Illegal load factor: " + 12 loadFactor); 13 this.loadFactor = loadFactor; 14 //根據初始化容量計算hashmap的閾值容量(hashmap真正的容量,必須是2的次方) 15 this.threshold = tableSizeFor(initialCapacity); 16 }
計算hashmap的容量get
1 // 根據給定的目標容量,計算一個2的次方 2 static final int tableSizeFor(int cap) { 3 int n = cap - 1; 4 n |= n >>> 1; 5 n |= n >>> 2; 6 n |= n >>> 4; 7 n |= n >>> 8; 8 n |= n >>> 16; 9 return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; 10 }
有參數map的構造方法:hash
1 public HashMap(Map<? extends K, ? extends V> m) { 2 this.loadFactor = DEFAULT_LOAD_FACTOR; 3 putMapEntries(m, false); 4 }
將map複製一份到本地,這個複製若是對於數值型則爲數值,對於引用型則爲地址it
1 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { 2 int s = m.size(); 3 //原來map的長度大於0處理 4 if (s > 0) { 5 if (table == null) { // pre-size 6 //根據實際數量計算須要多大的容量 7 float ft = ((float) s / loadFactor) + 1.0F; 8 int t = ((ft < (float) MAXIMUM_CAPACITY) ? (int) ft : MAXIMUM_CAPACITY); 9 //若是預估容量大於現有容量,則須要根據預估容量計算一個2的次方數 10 if (t > threshold) 11 threshold = tableSizeFor(t); 12 } 13 //若是實際容量大於閾值則須要擴容 14 else if (s > threshold) 15 resize(); 16 //擴容以後,將m的key和value複製一份到本地 17 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { 18 K key = e.getKey(); 19 V value = e.getValue(); 20 putVal(hash(key), key, value, false, evict); 21 } 22 } 23 }
1 //第一次調用初始化或者擴容 2 final Node<K,V>[] resize() { 3 //首次調用時爲null,則oldCap爲0 | 擴容時, 4 Node<K,V>[] oldTab = table; 5 int oldCap = (oldTab == null) ? 0 : oldTab.length; 6 int oldThr = threshold; 7 int newCap, newThr = 0; 8 //擴容時,若是目前容量已經超過最多容量,那麼默認值爲int最大,不然容量爲如今2倍 9 if (oldCap > 0) { 10 if (oldCap >= MAXIMUM_CAPACITY) { 11 threshold = Integer.MAX_VALUE; 12 return oldTab; 13 } 14 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && 15 oldCap >= DEFAULT_INITIAL_CAPACITY) 16 newThr = oldThr << 1; // double threshold 17 } 18 //初始化時newCap = oldThr = threshold 19 else if (oldThr > 0) // initial capacity was placed in threshold 20 newCap = oldThr; 21 else { // zero initial threshold signifies using defaults 22 newCap = DEFAULT_INITIAL_CAPACITY; 23 newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); 24 } 25 //初始化時newThr=newCap * loadFactor 26 if (newThr == 0) { 27 float ft = (float)newCap * loadFactor; 28 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? 29 (int)ft : Integer.MAX_VALUE); 30 } 31 threshold = newThr; 32 @SuppressWarnings({"rawtypes","unchecked"}) 33 //初始化時,建立一個長度爲threshold的Node數組,而後返回 34 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; 35 table = newTab; 36 if (oldTab != null) { 37 for (int j = 0; j < oldCap; ++j) { 38 Node<K,V> e; 39 if ((e = oldTab[j]) != null) { 40 oldTab[j] = null; 41 if (e.next == null) 42 newTab[e.hash & (newCap - 1)] = e; 43 else if (e instanceof TreeNode) 44 ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); 45 else { // preserve order 46 Node<K,V> loHead = null, loTail = null; 47 Node<K,V> hiHead = null, hiTail = null; 48 Node<K,V> next; 49 do { 50 next = e.next; 51 if ((e.hash & oldCap) == 0) { 52 if (loTail == null) 53 loHead = e; 54 else 55 loTail.next = e; 56 loTail = e; 57 } 58 else { 59 if (hiTail == null) 60 hiHead = e; 61 else 62 hiTail.next = e; 63 hiTail = e; 64 } 65 } while ((e = next) != null); 66 if (loTail != null) { 67 loTail.next = null; 68 newTab[j] = loHead; 69 } 70 if (hiTail != null) { 71 hiTail.next = null; 72 newTab[j + oldCap] = hiHead; 73 } 74 } 75 } 76 } 77 } 78 return newTab; 79 }