首先从一条简单的语句开始,创建了一个hashmap对象:
Map<String,String> hashmap = new HashMap<String,String>();
调用hashmap类无参数构造方法,使用默认转载因子,
1 public HashMap() { 2 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 3 }
默认装载因子只有在构造器不指定的情况下使用
1 /** 2 * The load factor used when none specified in constructor. 3 */ 4 static final float DEFAULT_LOAD_FACTOR = 0.75f;
hashmap还有三个重载的构造方法,分别是:
有装载因子入参的构造方法
1 public HashMap(int initialCapacity) { 2 this(initialCapacity, DEFAULT_LOAD_FACTOR); 3 }
有初始化容器容量以及装载因子的构造方法
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的容量
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的构造方法:
1 public HashMap(Map<? extends K, ? extends V> m) { 2 this.loadFactor = DEFAULT_LOAD_FACTOR; 3 putMapEntries(m, false); 4 }
将map复制一份到本地,这个复制如果对于数值型则为数值,对于引用型则为地址
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 }