本文基于1.8的源码说明
DEFAULT_INITIAL_CAPACITY:初始化大小:16
MAXIMUM_CAPACITY:最大数组大小(最接近int最大值的2的n次冥):1<<30
DEFAULT_LOAD_FACTOR:负载因子(数组占用率达到多少开始扩容/并不绝对,具体取决于扩容阈值 threshold):0.75f
TREEIFY_THRESHOLD:由链表转为红黑树的阈值:8
UNTREEIFY_THRESHOLD:由红黑树转为链表的阈值:6
MIN_TREEIFY_CAPACITY:转红黑树时判断数组容量是否大于这个值,大于则转红黑树,小于则不转:64
static final int hash(Object key) :hash散列算法,计算key的哈希值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
static Class> comparableClassFor(Object x):
static int compareComparables(Class> kc, Object k, Object x):
static final int tableSizeFor(int cap):是返回大于输入参数且最近的2的整数次幂的数(第一次使用是在有参构造时)
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
final void putMapEntries(Map extends K, ? extends V> m, boolean evict):
public V get(Object key):根据key获取value
public V get(Object key) {
Node e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node
final NodegetNode(int hash, Object key) { Node [] tab; Node first, e; int n; K k; //节点不为空 if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { //判断首个节点是否是我们要寻找的key if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; //第一个节点不是,则往下寻找 if ((e = first.next) != null) { //红黑树则执行红黑树的查找方法 if (first instanceof TreeNode) return ((TreeNode )first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
public boolean containsKey(Object key):判断是否存在该key
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
public V put(K key, V value):往hashMap里面存入键值对
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict):往hashMap里面存入键值对
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
Node[] tab; Node p; int n, i;
//如果数组为null或者长度为0则扩容(此时表示为初始化之后第一次put)
if ((tab = table) == null || (n = tab.length) == 0)
//n赋值为扩容后数组的长度
n = (tab = resize()).length;
//如果该节点为空,则直接插入((n - 1) & hash 为计算数组下标算法)
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
//如果该节点不为空,则需要在链表或者树后面添加节点
Node e; K k;
//节点的hash值相同,并且key值相同或者equlse()返回true,表示该key值以存在
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
//如果节点是树节点,则调用树节点的put方法、并返回
e = ((TreeNode)p).putTreeval(this, tab, hash, key, value);
else {
//循环链表节点
for (int binCount = 0; ; ++binCount) {
//如果某节点的next为空,说明该节点不存在,并且需要插入在该节点的next位置
if ((e = p.next) == null) {
//插入
p.next = newNode(hash, key, value, null);
//判断bincount和树化阈值,大于等于8就树化
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//树化
treeifyBin(tab, hash);
break;
}
//和上面一样,判断key值是否相等,相等则表示已存在,直接返回
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//表示该key的节点存在、e为插入的新节点或者已存在的该key的节点
if (e != null) { // existing mapping for key
V oldValue = e.value;
//如果key值已存在,则替换该key的value
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
//fail fast机制的操作数+1(链表或者树后面增加节点,该值不增加,不会导致fail fast)
++modCount;
//size+1 map的size+1 并判断是否需要扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
final Node
final Node[] resize() { Node [] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; //判断原来的数组是否是第一次扩容、大于0则不是 if (oldCap > 0) { //是否大于最大长度,如果大于,则将扩容阈值增加打int最大值 if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } //如果不大于,并且数组大于等于默认容量 则正常扩容、扩容一倍 //如果新容量等于最大值了并且数组大于等于默认容量,则不进行新阈值x2操作,此时newThr等于0,否则进行 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // double threshold } //如果是第一次扩容,则判断是否是有参构造,如果是有参构造,直接将扩容阈值设置为新容量 else if (oldThr > 0) // initial capacity was placed in threshold newCap = oldThr; //这里表示是第一次扩容,并且是无参构造、则将新容量,新阈值设置为默认值 else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } //如果新阈值没赋值,则进行赋值操作 if (newThr == 0) { float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node [] newTab = (Node [])new Node[newCap]; table = newTab; //原数组不为空 if (oldTab != null) { for (int j = 0; j < oldCap; ++j) { Node e; if ((e = oldTab[j]) != null) { oldTab[j] = null; if (e.next == null) //如果是单节点,则直接重新执行散列算法插入赋值 newTab[e.hash & (newCap - 1)] = e; //如果是树节点,则执行树节点的插入操作 else if (e instanceof TreeNode) ((TreeNode )e).split(this, newTab, j, oldCap); //这个分支表示为链表节点 else { // preserve order Node loHead = null, loTail = null; Node hiHead = null, hiTail = null; Node next; //将原来的链表拆分为高位和低位两个链表 do { //next指向下一个 next = e.next; //等于0为低位、低位head为lohead,循环结束直接赋值为此节点,高位相同 if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } //否则为高位 else { if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); //判断不为空则赋值,注意低位的下标不变,高位的下标为原来的下标+原来的容量 if (loTail != null) { loTail.next = null; newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; newTab[j + oldCap] = hiHead; } } } } } return newTab; }
final void treeifyBin(Node
final void treeifyBin(Node[] tab, int hash) { int n, index; Node e; //如果数组为空或者数组长度小于64则直接扩容 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); //节点不为空,则转红黑树 else if ((e = tab[index = (n - 1) & hash]) != null) { TreeNode hd = null, tl = null; //hd为红黑树根节点,循环完毕直接赋值 do { TreeNode p = replacementTreeNode(e, null); if (tl == null) hd = p; else { p.prev = tl; tl.next = p; } tl = p; } while ((e = e.next) != null); //平衡等一些列后续操作,后续再学习 if ((tab[index] = hd) != null) hd.treeify(tab); } }
public V remove(Object key):移除节点
public V remove(Object key) {
Node e;
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
public boolean containsValue(Object value):判断是否存在value
public boolean containsValue(Object value) {
Node[] tab; V v;
if ((tab = table) != null && size > 0) {
for (int i = 0; i < tab.length; ++i) {
for (Node e = tab[i]; e != null; e = e.next) {
if ((v = e.value) == value ||
(value != null && value.equals(v)))
return true;
}
}
}
return false;
}
public Set keySet():获得key集合
public SetkeySet() { Set ks = keySet; if (ks == null) { ks = new KeySet(); keySet = ks; } return ks; }
public Collection values():获取value集合
public Collectionvalues() { Collection vs = values; if (vs == null) { vs = new Values(); values = vs; } return vs; }
public Set
public Set> entrySet() { Set > es; return (es = entrySet) == null ? (entrySet = new EntrySet()) : es; }
final Node
final NoderemoveNode(int hash, Object key, Object value, boolean matchValue, boolean movable) { Node [] tab; Node p; int n, index; //节点不为空 if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) { Node node = null, e; K k; V v; //如果第一个是要删除的key,直接删除 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; else if ((e = p.next) != null) { //执行树的查找方法 if (p instanceof TreeNode) node = ((TreeNode )p).getTreeNode(hash, key); //否则是链表查找 else { do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break; } p = e; } while ((e = e.next) != null); } } //如果查找的节点不为空 if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { if (node instanceof TreeNode) ((TreeNode )node).removeTreeNode(this, tab, movable); else if (node == p) tab[index] = node.next; else p.next = node.next; ++modCount; --size; afterNodeRemoval(node); return node; } } return null; }



