首先hashMap会根据传入的key值进行hash算法计算出hashcode,hashcode 就是桶值,然后查看桶是不是空的如果是空的就直接放进去,如果不是空的就看是不是红黑树,不是红黑树的话就是链表,将节点挂在链表后面,判断链表长度是否大于8,如果大于8就将这个链表树化。
部分成员变量如下: //初始值,为16,必须为2的次幂 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //当容量被占满0.75时就需要reSize扩容 static final float DEFAULT_LOAD_FACTOR = 0.75f; //链表长度到8,就转为红黑树 static final int TREEIFY_THRESHOLD = 8; // 树大小为6,就转回链表 static final int UNTREEIFY_THRESHOLD = 6;
hashMap中有一个 Node<K, V> table 桶数组
首先是hash算法:就是将key值和自己高16位异或运算。
1 static final int hash(Object key) { 2 int h; 3 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 4 }
然后是调用putVal方法:
1 public V put(K key, V value) { 2 return putVal(hash(key), key, value, false, true); 3 }
putVal方法:
1 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 2 boolean evict) { 3 HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i; 4 //空表直接扩容 5 if ((tab = table) == null || (n = tab.length) == 0) 6 n = (tab = resize()).length; 7 //n是扩容之后的数组长度,(n - 1) & hash = hash % n - 1 8 //桶数组是空的,直接将节点放进去 9 if ((p = tab[i = (n - 1) & hash]) == null) 10 tab[i] = newNode(hash, key, value, null); 11 else { 12 //桶不是空的判断第一个节点是不是就是你要替换的那个节点 13 HashMap.Node<K,V> e; K k; 14 if (p.hash == hash && 15 ((k = p.key) == key || (key != null && key.equals(k)))) 16 e = p;//节点交换最后统一更换这个e节点的value 17 //判断是不是树节点 18 else if (p instanceof HashMap.TreeNode) 19 //调用红黑树的put方法,将替换后的节点返回 20 e = ((HashMap.TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); 21 else { 22 //最后就是链表 23 for (int binCount = 0; ; ++binCount) { 24 //遍历链表,找到一样的节点,如果遍历到最后就将节点放在链表最后面, 25 if ((e = p.next) == null) { 26 p.next = newNode(hash, key, value, null); 27 //节点放完之后,判断链表的长度打没达到树化的标准 28 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st 29 treeifyBin(tab, hash);//树化 30 break; 31 } 32 //找到节点 33 if (e.hash == hash && 34 ((k = e.key) == key || (key != null && key.equals(k)))) 35 break; 36 p = e; 37 } 38 } 39 //替换值,然后返回旧值 40 if (e != null) { // existing mapping for key 41 V oldValue = e.value; 42 if (!onlyIfAbsent || oldValue == null) 43 e.value = value; 44 //空方法 45 afterNodeAccess(e); 46 return oldValue; 47 } 48 } 49 ++modCount; 50 //判断size值打没达到扩容的标准 51 if (++size > threshold) 52 resize(); 53 //一些空方法 54 afterNodeInsertion(evict); 55 return null; 56 }
简单的源码注释,越学越快乐!