JDK8 HashMap源码浅析

	DEFAULT_INITIAL_CAPACITY = 16; // 默认数组长度

	MAXIMUM_CAPACITY = 1 << 30; // 大于1000,000,000,即10亿

	DEFAULT_LOAD_FACTOR = 0.75f; // 用于计算threshold

	TREEIFY_THRESHOLD = 8; // 单向链表转双向链表和红黑树需要满足的第一个条件

	UNTREEIFY_THRESHOLD = 6; // 在resize操作时,双向链表和红黑树转单向链表需要满足的条件

	MIN_TREEIFY_CAPACITY = 64; // 单向链表转双向链表和红黑树需要满足的第二个条件

	Node<K,V>[] table; // 数组

	int threshold; // The next size value at which to resize (capacity * load factor). // 扩容的条件

增加元素

    /**
     * 1.为什么HashMap的key可以是null? 答: (key == null) ? 0 : blablabla。
     * 2.为什么要通过“(h = key.hashCode()) ^ (h >>> 16)”来生成哈希值? 答: 目的是减少hash collision,但我还理解不了其原理。
     */
	static final int hash(Object key) {
		int h;
		return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
	}
	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 = 16,代表数组长度 threshold = 12,代表扩容阈值
			 */
			n = (tab = resize()).length;

		if ((p = tab[i = (n - 1) & hash]) == null) // “(n - 1) & hash”是哈希函数,与扩容时候的高低位机制紧密联系

			// p = null => 没有发生哈希冲突

			tab[i] = newNode(hash, key, value, null);

		else {
			// 发生哈希冲突,p代表发生冲突的位置上的节点

			Node<K, V> e;
			K k;

			if (p.hash == hash
					&& ((k = p.key) == key || (key != null && key.equals(k))))

				// 找到哈希值一样,key值也一样的节点。该节点可能是红黑树节点,也可能不是

				e = p;

			else if (p instanceof TreeNode) // TreeNode是Node的子类

				// p是红黑树节点

				e = ((TreeNode<K, V>) p)
						.putTreeVal(this, tab, hash, key, value); // 尝试在红黑树中寻找哈希值一样,key值也一样的节点。若找到,则返回该节点,否则在红黑树中插入新节点,并返回null

			else {
				// 单向链表节点

				for (int binCount = 0;; ++binCount) {

					if ((e = p.next) == null) {
						// e是null,p代表链表的最后一个节点

						// 把新节点添加到链表尾部
						p.next = newNode(hash, key, value, null);

						if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
							// 因为链表长度大于8,所以可能要把链表转红黑树
							treeifyBin(tab, hash);
						break;
					}

					// 程序能走到这里,说明e不是null

					if (e.hash == hash
							&& ((k = e.key) == key || (key != null && key
									.equals(k))))

						// 找到哈希值一样,key值也一样的节点,用e记录

						break;

					p = e;
				}
			}
			if (e != null) { // existing mapping for key

				// e不是null,说明e代表哈希值一样,key值也一样的节点,需要替换其value

				V oldValue = e.value;
				if (!onlyIfAbsent || oldValue == null)
					e.value = value;
				afterNodeAccess(e);
				return oldValue;
			}
		}

		++modCount;

		if (++size > threshold)

			// 节点数量太多

			resize(); // 进行扩容

		afterNodeInsertion(evict);
		return null;
	}
	/**
	 * 第一次执行:初始化的时候
	 *
	 * 执行完后:
	 * 数组table的长度是16
	 * threshold是12
	 *
	 */
    final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table; // table = null
        int oldCap = (oldTab == null) ? 0 : oldTab.length; // 0
        int oldThr = threshold; // 0
        int newCap, newThr = 0;
        if (oldCap > 0) {
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            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; // 16
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); // 0.75 * 16 = 12
        }
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr; // 12
        @SuppressWarnings({"rawtypes","unchecked"})
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; // newCap = 16
        table = newTab;
        if (oldTab != null) {
            for (int j = 0; j < oldCap; ++j) {
                Node<K,V> 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<K,V>)e).split(this, newTab, j, oldCap);
                    else { // preserve order
                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
                        do {
                            next = e.next;
                            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 TreeNode<K, V> putTreeVal(HashMap<K, V> map, Node<K, V>[] tab, int h,
			K k, V v) {
		Class<?> kc = null;
		boolean searched = false;
		TreeNode<K, V> root = (parent != null) ? root() : this;

		for (TreeNode<K, V> p = root;;) {
			int dir, ph;
			K pk;

			if ((ph = p.hash) > h)

				// 往左子树寻找

				dir = -1;
			else if (ph < h)

				// 往右子树寻找

				dir = 1;

			// 往下的逻辑:ph = h

			else if ((pk = p.key) == k || (k != null && k.equals(pk))) // 总结经验:要认真重写key的hashCode和equals方法。若key实现了Comparable接口,当compareTo返回值为0时,equals方法应返回true

				// 哈希值一样,key值也一样的节点

				return p;

			// 哈希值一样,key值不一样

			else if ((kc == null && // 若key没有实现Comparable接口
					(kc = comparableClassFor(k)) == null)
					|| // 或者Comparable也无法给出判断(compareTo方法返回值是0)
					(dir = compareComparables(kc, k, pk)) == 0) {

				// key没有实现Comparable接口,或者Comparable不起作用 => 不知道该往左子树找,还是往右子树找 => 先在左子树里找,找不到的话再从右子树里找,相当于遍历整棵树,而这波操作只需进行一次
				
				// 总结经验:别用null作为key,让key实现Comparable接口,并确保compareTo返回值为0时,equals方法返回true

				if (!searched) {

					// searched为false时才进来,说明之前没有遍历过

					TreeNode<K, V> q, ch;
					searched = true; // 确保只会遍历一次
					if (((ch = p.left) != null && (q = ch.find(h, k, kc)) != null)
							|| ((ch = p.right) != null && (q = ch
									.find(h, k, kc)) != null))
						return q;
				}
				
				// 遍历完整棵树后都找不到,则使用identityHashCode
				
				dir = tieBreakOrder(k, pk);
			}

			TreeNode<K, V> xp = p;
			if ((p = (dir <= 0) ? p.left : p.right) == null) {

				// 在红黑树中,xp是新节点的父节点;在双向链表中,xp是新节点的前驱节点

				Node<K, V> xpn = xp.next; // TreeNode双向链表中xp的后继节点
				TreeNode<K, V> x = map.newTreeNode(h, k, v, xpn); // newTreeNode里头:x.next = xpn
				if (dir <= 0)
					xp.left = x;
				else
					xp.right = x;
				xp.next = x;
				x.parent = x.prev = xp;
				if (xpn != null)
					((TreeNode<K, V>) xpn).prev = x; // 与newTreeNode里头的x.next = xpn相呼应
				moveRootToFront(tab, balanceInsertion(root, x));
				return null;
			}
		}
	}
	/**
	 * 当单个链表长度大于8,要不扩容,要不把该链表转红黑树
	 */
	final void treeifyBin(Node<K, V>[] tab, int hash) {
		int n, index;
		Node<K, V> e;

		if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)

			// 数组长度小于64

			resize(); // 扩容

		else if ((e = tab[index = (n - 1) & hash]) != null) {

			// 数组长度大于或等于64

			TreeNode<K, V> hd = null, tl = null; // hd是链表头,tl是链表尾

			// TreeNode是Node的子类,用TreeNode构建一模一样的链表

			do {
				TreeNode<K, V> 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) // tab[index] = hd:用TreeNode构建双向链表替代原来的Node单向链表
				hd.treeify(tab);
		}
	}
	final void treeify(Node<K, V>[] tab) {
		TreeNode<K, V> root = null;

		for (TreeNode<K, V> x = this, next; x != null; x = next) {
			next = (TreeNode<K, V>) x.next; // 没有破坏TreeNode双向链表
			x.left = x.right = null;

			if (root == null) {
				x.parent = null;
				x.red = false;
				root = x;
			}

			else {
				K k = x.key;
				int h = x.hash;
				Class<?> kc = null;

				for (TreeNode<K, V> p = root;;) {
					int dir, ph;
					K pk = p.key;

					if ((ph = p.hash) > h)

						// 往左子树

						dir = -1;
					else if (ph < h)

						// 往右子树

						dir = 1;

					// 下面的逻辑:ph = h

					// 除非程序员挖坑,否则一般都不会满足下面的条件

					else if ((kc == null && // 若key没有实现Comparable接口
							(kc = comparableClassFor(k)) == null)
							|| (dir = compareComparables(kc, k, pk)) == 0) // 或者Comparable无法给出判断(compareTo方法返回值是0)

						// 哈希值一样,key值也一样 => 不知道该放左子树还是右子树

						dir = tieBreakOrder(k, pk);

					TreeNode<K, V> xp = p; // xp是新节点的父节点
					if ((p = (dir <= 0) ? p.left : p.right) == null) {

						// 插入新节点

						x.parent = xp;
						if (dir <= 0)
							xp.left = x;
						else
							xp.right = x;
						root = balanceInsertion(root, x); // 调整
						break;
					}
				}
			}
		}
		moveRootToFront(tab, root);
	}
	/**
	 * Tie-breaking utility for ordering insertions when equal hashCodes and
	 * non-comparable. We don't require a total order, just a consistent
	 * insertion rule to maintain equivalence across rebalancings. Tie-breaking
	 * further than necessary simplifies testing a bit.
	 */
	static int tieBreakOrder(Object a, Object b) {
		int d;
		if (a == null
				|| b == null
				|| // a或者b是null
				(d = a.getClass().getName().compareTo(b.getClass().getName())) == 0) // 又或者连类名都相等
			d = (System.identityHashCode(a) <= System.identityHashCode(b) ? -1
					: 1); // 不同对象的identityHashCode必然不同
		return d;
	}
	static <K, V> TreeNode<K, V> balanceInsertion(TreeNode<K, V> root,
			TreeNode<K, V> x) {
		x.red = true; // 新节点都是红色
		for (TreeNode<K, V> xp, xpp, xppl, xppr;;) { // xp是x的父节点,xpp是x的祖父节点,xppl和xppr是x的祖父节点的左右孩子
			if ((xp = x.parent) == null) {

				// x没有父节点 => x是根节点

				x.red = false; // 把x设为黑色,不需调整
				return x;
			}

			else if (!xp.red || (xpp = xp.parent) == null)

				// x的父节点是黑色,或者x没有祖父节点

				return root; // 不需调整

			// 往下的逻辑:x的父节点是红色,且x有祖父节点

			if (xp == (xppl = xpp.left)) {

				// x的父节点是祖父节点的左孩子

				if ((xppr = xpp.right) != null && xppr.red) {

					// x的祖父节点有一个红色的右孩子 => x的叔叔节点是红色

					xppr.red = false; // 把叔叔节点设为黑色
					xp.red = false; // 把父节点设为黑色
					xpp.red = true; // 把祖父节点设为红色
					x = xpp; // 把祖父节点视为新节点继续操作
				}

				else {

					// x没有叔叔节点(因为x的父节点是红色,所以x不可能有一个黑色的叔叔节点)

					if (x == xp.right) {

						// x是父节点的右孩子(即LR),对父节点进行左旋操作,从而转化为LL

						root = rotateLeft(root, x = xp);
						xpp = (xp = x.parent) == null ? null : xp.parent;
					}

					// LL

					if (xp != null) {
						xp.red = false; // 把父节点设为黑色
						if (xpp != null) {
							xpp.red = true; // 把祖父节点设为红色
							root = rotateRight(root, xpp); // 对父节点进行右旋操作
						}
					}
				}
			}

			else {

				// 父节点是祖父节点的右孩子

				if (xppl != null && xppl.red) {
					xppl.red = false;
					xp.red = false;
					xpp.red = true;
					x = xpp;
				} else {
					if (x == xp.left) {
						root = rotateRight(root, x = xp);
						xpp = (xp = x.parent) == null ? null : xp.parent;
					}
					if (xp != null) {
						xp.red = false;
						if (xpp != null) {
							xpp.red = true;
							root = rotateLeft(root, xpp);
						}
					}
				}
			}
		}
	}
	/**
	 * Ensures that the given root is the first node of its bin.
	 *
	 * 把红黑树的节点调整为TreeNode双向链表中的第一个节点
	 */
	static <K, V> void moveRootToFront(Node<K, V>[] tab, TreeNode<K, V> root) {
		int n; // 数组长度
		if (root != null && tab != null && (n = tab.length) > 0) {

			int index = (n - 1) & root.hash;
			TreeNode<K, V> first = (TreeNode<K, V>) tab[index];

			if (root != first) {
				Node<K, V> rn; // TreeNode双向链表中root的后继
				tab[index] = root;
				TreeNode<K, V> rp = root.prev; // TreeNode双向链表中root的前驱

				if ((rn = root.next) != null)
					((TreeNode<K, V>) rn).prev = rp;

				if (rp != null)
					rp.next = rn;

				if (first != null)
					first.prev = root;

				root.next = first;
				root.prev = null;
			}

			assert checkInvariants(root);
		}
	}
	static <K, V> TreeNode<K, V> rotateLeft(TreeNode<K, V> root,
			TreeNode<K, V> p) {
		TreeNode<K, V> r, pp, rl; // r是p的右孩子,pp是p的父节点,rl是r的左孩子
		if (p != null && (r = p.right) != null) {
			if ((rl = p.right = r.left) != null)
				rl.parent = p;

			if ((pp = r.parent = p.parent) == null)

				// p没有祖父节点 => p是根节点

				(root = r).red = false; // 把r设为根节点,颜色为黑

			// 下面的逻辑:p有祖父节点

			else if (pp.left == p)
				pp.left = r;
			else
				pp.right = r;

			r.left = p;
			p.parent = r;
		}
		return root;
	}
	/**
	 * 检查双向链表和红黑树是否合规
	 */
	static <K, V> boolean checkInvariants(TreeNode<K, V> t) {
		TreeNode<K, V> tp = t.parent, tl = t.left, tr = t.right, tb = t.prev, tn = (TreeNode<K, V>) t.next;
		if (tb != null && tb.next != t)
			return false;
		if (tn != null && tn.prev != t)
			return false;
		if (tp != null && t != tp.left && t != tp.right)
			return false;
		if (tl != null && (tl.parent != t || tl.hash > t.hash))
			return false;
		if (tr != null && (tr.parent != t || tr.hash < t.hash))
			return false;
		if (t.red && tl != null && tl.red && tr != null && tr.red)
			return false;
		if (tl != null && !checkInvariants(tl))
			return false;
		if (tr != null && !checkInvariants(tr))
			return false;
		return true;
	}
	/**
	 * 第二次执行:第一次扩容
	 */
	final Node<K, V>[] resize() {
		Node<K, V>[] oldTab = table; // table是长度为16的数组
		int oldCap = (oldTab == null) ? 0 : oldTab.length; // 16
		int oldThr = threshold; // 12
		int newCap, newThr = 0;

		if (oldCap > 0) {

			if (oldCap >= MAXIMUM_CAPACITY) {

				// oldCap大于10亿

				threshold = Integer.MAX_VALUE; // hardcode最大值,不再扩容
				return oldTab;
			}

			else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && // newCap变为原来的2倍,即32
					oldCap >= DEFAULT_INITIAL_CAPACITY)

				// newThr变为原来的2倍,即24,newThr依然等于DEFAULT_LOAD_FACTOR * 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; // 24
		@SuppressWarnings({ "rawtypes", "unchecked" })
		Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap]; // newTab代表长度为32的新数组
		table = newTab;

		if (oldTab != null) {

			// 把节点从旧表迁移到新表

			for (int j = 0; j < oldCap; ++j) {
				Node<K, V> e;
				if ((e = oldTab[j]) != null) {

					// e != null,需要migrate

					oldTab[j] = null; // help GC

					if (e.next == null)

						// 普通节点(既非链表,也非红黑树节点)

						newTab[e.hash & (newCap - 1)] = e;

					else if (e instanceof TreeNode)

						// 红黑树节点

						((TreeNode<K, V>) e).split(this, newTab, j, oldCap); // split方法里涉及高低位

					else { // preserve order

						// 链表——高低位

						Node<K, V> loHead = null, loTail = null; // 低位链表(0-15)
						Node<K, V> hiHead = null, hiTail = null; // 高位链表(16-31)
						Node<K, V> next;

						do {
							next = e.next;
							if ((e.hash & oldCap) == 0) { // oldCap = 16,二进制为10000,这里的判断是看看哈希值的第5位是否为0

								// 第5位是0,哈希值不变,添加到低位链表

								if (loTail == null)

									// 初始化

									loHead = e;
								else
									loTail.next = e;
								loTail = e;
							}

							else {

								// 第5位是1,哈希值会增加16,添加到高位链表

								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; // 哈希值增加16
						}
					}
				}
			}
		}
		return newTab;
	}
	final TreeNode<K, V> find(int h, Object k, Class<?> kc) {
		TreeNode<K, V> p = this;
		do {
			int ph, dir;
			K pk;
			TreeNode<K, V> pl = p.left, pr = p.right, q;
			if ((ph = p.hash) > h)
				p = pl; // 往左子树
			else if (ph < h)
				p = pr; // 往右子树
			else if ((pk = p.key) == k || (k != null && k.equals(pk)))
				return p; // 找到哈希值一样,key值也一样的节点

			// 往下的逻辑:ph = h

			// 除非程序员挖坑,否则一般都不会满足下面的条件

			// 哈希值一样(ph = h),但key不相同(k.equals(pk)返回false) => 不知道该往左子树找,还是往右子树找

			else if (pl == null)
				p = pr; // 没有左孩子,往右子树找
			else if (pr == null)
				p = pl; // 有左孩子,但没有右孩子,往左子树找

			// 既有左孩子,又有右孩子

			else if ((kc != null || (kc = comparableClassFor(k)) != null)
					&& (dir = compareComparables(kc, k, pk)) != 0)

				// 若key实现Comparable了接口,且compareTo方法能给出明确的判断(compareTo方法返回值不是0)

				p = (dir < 0) ? pl : pr;

			// key没有实现Comparable接口,或者compareTo方法返回值是0

			else if ((q = pr.find(h, k, kc)) != null) // 先从右子树找,找到就返回
				return q;
			else
				p = pl; // 在右子树里找不到,再从左子树找
		} while (p != null);
		return null;
	}
	/**
	 * Splits nodes in a tree bin into lower and upper tree bins, or untreeifies
	 * if now too small. Called only from resize; see above discussion about
	 * split bits and indices.
	 *
	 * tab是新数组,bit是旧数组的长度,下面假设bit是16
	 */
	final void split(HashMap<K, V> map, Node<K, V>[] tab, int index, int bit) {
		TreeNode<K, V> b = this;
		// Relink into lo and hi lists, preserving order
		TreeNode<K, V> loHead = null, loTail = null; // 低位链表(0-15)
		TreeNode<K, V> hiHead = null, hiTail = null; // 高位链表(16-31)
		int lc = 0, hc = 0;
		for (TreeNode<K, V> e = b, next; e != null; e = next) {
			next = (TreeNode<K, V>) e.next;
			e.next = null;
			if ((e.hash & bit) == 0) {
				if ((e.prev = loTail) == null)
					loHead = e;
				else
					loTail.next = e;
				loTail = e;
				++lc;
			} else {
				if ((e.prev = hiTail) == null)
					hiHead = e;
				else
					hiTail.next = e;
				hiTail = e;
				++hc;
			}
		}
		
		/* 已经把一个TreeNode双向链表拆分成两个TreeNode双向链表,但并没有把一棵TreeNode红黑树拆分成两棵 */

		if (loHead != null) {
			if (lc <= UNTREEIFY_THRESHOLD)
				tab[index] = loHead.untreeify(map); // TreeNode双向链表转Node单向链表
			else {
				tab[index] = loHead;
				if (hiHead != null) // (else is already treeified)
					loHead.treeify(tab); // 使用低位TreeNode双向链表构造一棵新的红黑树
			}
		}
		if (hiHead != null) {
			if (hc <= UNTREEIFY_THRESHOLD)
				tab[index + bit] = hiHead.untreeify(map); // TreeNode双向链表转Node单向链表
			else {
				tab[index + bit] = hiHead;
				if (loHead != null)
					hiHead.treeify(tab); // 使用高位TreeNode双向链表构造一棵新的红黑树
			}
		}
	}

删除元素

	final Node<K, V> removeNode(int hash, Object key, Object value,
			boolean matchValue, boolean movable) { // matchValue = false,
													// movable = true
		Node<K, V>[] tab;
		Node<K, V> p; // 哈希后命中的数组元素
		int n, index; // n代表数组长度,index是哈希后得到的数组下标

		if ((tab = table) != null && (n = tab.length) > 0
				&& (p = tab[index = (n - 1) & hash]) != null) {
			Node<K, V> node = null, e;
			K k;
			V v;

			if (p.hash == hash
					&& ((k = p.key) == key || (key != null && key.equals(k))))

				// 找到哈希值一样,key值也一样的节点。该节点可能是红黑树节点,也可能不是

				node = p;

			// 往下的逻辑:第一个节点不是要删除的元素

			else if ((e = p.next) != null) {
				if (p instanceof TreeNode)

					// 红黑树节点

					node = ((TreeNode<K, V>) p).getTreeNode(hash, key);
				else {

					// 单向链表节点

					do {
						if (e.hash == hash
								&& ((k = e.key) == key || (key != null && key
										.equals(k)))) {

							// 找到哈希值一样,key值也一样的节点

							node = e;
							break;
						}
						p = e; // p是要删除的节点的前驱
					} while ((e = e.next) != null);
				}
			}

			if (node != null
					&& (!matchValue || (v = node.value) == value || (value != null && value
							.equals(v)))) {
				if (node instanceof TreeNode)

					// 红黑树节点

					((TreeNode<K, V>) node).removeTreeNode(this, tab, movable);

				// 往下的逻辑:单向链表节点

				else if (node == p)

					// 第一个节点就是要删除的元素,让其后继节点顶上

					tab[index] = node.next;
				else
					p.next = node.next;
				// 是否应该按照惯例加多一行代码:“node.next = null”?

				++modCount;
				--size;
				afterNodeRemoval(node);
				return node;
			}
		}
		return null;
	}
	/**
	 * Removes the given node, that must be present before this call. This is
	 * messier than typical red-black deletion code because we cannot swap the
	 * contents of an interior node with a leaf successor that is pinned by
	 * "next" pointers that are accessible independently during traversal. So
	 * instead we swap the tree linkages. If the current tree appears to have
	 * too few nodes, the bin is converted back to a plain bin. (The test
	 * triggers somewhere between 2 and 6 nodes, depending on tree structure).
	 *
	 * 删除当前对象(this)所代表的红黑树节点
	 */
	final void removeTreeNode(HashMap<K, V> map, Node<K, V>[] tab,
			boolean movable) { // movable = true
		int n; // 数组长度

		if (tab == null || (n = tab.length) == 0)
			return;

		int index = (n - 1) & hash; // 当前对象所在的数组下标
		TreeNode<K, V> first = (TreeNode<K, V>) tab[index], root = first, rl; // first表示双向链表中的第一个节点,也是根节点,rl表示根节点的左孩子

		TreeNode<K, V> succ = (TreeNode<K, V>) next, pred = prev; // 当前对象在双向链表中的后继和前驱节点

		if (pred == null) // 若当前对象没有前驱节点,说明当前对象是双向链表中的第一个节点,也是红黑树的根节点
			tab[index] = first = succ; // 让当前对象的后继节点顶上
		// 是否应该按照惯例加多一行代码:“next = null”?

		else
			// 当前对象不是双向链表中的第一个节点
			pred.next = succ;

		if (succ != null)
			// 当前对象不是双向链表中的最后一个节点
			succ.prev = pred;

		/* 已完成从双向链表中删除当前对象,但尚未从红黑树中删除当前对象 */

		if (first == null)
			return; // 空树,不需调整,直接返回

		if (root.parent != null)
			root = root.root();

		if (root == null || (movable && (root.right == null // 若根节点没有右孩子,则红黑树最多有2个节点
				|| (rl = root.left) == null // 若根节点没有左孩子,则红黑树最多有2个节点
		|| rl.left == null))) { // 若根节点的左孩子没有左孩子,则红黑树最多可以有10个节点吧?

			// 双向链表和红黑树转单向链表

			tab[index] = first.untreeify(map); // too small
			return;
		}

		TreeNode<K, V> p = this, pl = left, pr = right, replacement; // p代表当前对象
		if (pl != null && pr != null) {

			// 当前对象有两个孩子

			TreeNode<K, V> s = pr, sl;
			while ((sl = s.left) != null)
				// find successor
				s = sl;

			// s是“右边最远的左下”子孙节点

			boolean c = s.red;
			s.red = p.red;
			p.red = c; // swap colors => 为什么要交换颜色,直接交换节点的value不就行了吗? => 因为接下来会交换p和s两个对象

			TreeNode<K, V> sr = s.right;
			TreeNode<K, V> pp = p.parent;

			/* 开始交换p和s */

			if (s == pr) { // p was s's direct parent => 当前对象是s的父节点
				p.parent = s;
				s.right = p;
			} else {

				// 当前对象不是s的父节点

				TreeNode<K, V> sp = s.parent;

				if ((p.parent = sp) != null) {
					if (s == sp.left)
						sp.left = p;
					else
						sp.right = p;
				}

				if ((s.right = pr) != null)
					pr.parent = s;
			}

			p.left = null; // 不用慌,前面用pl保存了左子树

			if ((p.right = sr) != null)
				sr.parent = p;

			if ((s.left = pl) != null)
				pl.parent = s;

			if ((s.parent = pp) == null)
				root = s;
			else if (p == pp.left)
				pp.left = s;
			else
				pp.right = s;

			/* 已完成当前对象和s的交换,现在当前对象可能是叶子节点,也可能有一个右孩子 */

			if (sr != null)
				// p有一个右孩子
				replacement = sr;
			else
				// p是叶子节点
				replacement = p;
		}

		// 当前对象可能是叶子节点,也可能有一个孩子

		else if (pl != null)
			// 当前对象只有左孩子
			replacement = pl;
		else if (pr != null)
			// 当前对象只有右孩子
			replacement = pr;
		else
			// 当前对象是叶子节点
			replacement = p;

		if (replacement != p) {

			// replacement没有指向当前对象,说明当前对象不是叶子节点,此时要先删除,再调整。又因为当前对象只能有一个孩子,所以当前对象是黑色,replacement是红色。

			TreeNode<K, V> pp = replacement.parent = p.parent;

			if (pp == null)
				root = replacement;
			else if (p == pp.left)
				pp.left = replacement;
			else
				pp.right = replacement;

			p.left = p.right = p.parent = null;
		}

		TreeNode<K, V> r = p.red ? root : balanceDeletion(root, replacement); // 被删除的节点是黑色才调整

		if (replacement == p) { // detach

			// replacement指向当前对象,说明当前对象是叶子节点,此时要先调整,再删除

			TreeNode<K, V> pp = p.parent;
			p.parent = null;

			if (pp != null) {
				if (p == pp.left)
					pp.left = null;
				else if (p == pp.right)
					pp.right = null;
			}
		}

		if (movable)
			moveRootToFront(tab, r);
	}
	static <K, V> TreeNode<K, V> balanceDeletion(TreeNode<K, V> root,
			TreeNode<K, V> x) {
		for (TreeNode<K, V> xp, xpl, xpr;;) { // xp是x的父节点,xpl和xpr是x的父节点的左右孩子
			if (x == null || x == root)
				return root;
			else if ((xp = x.parent) == null) {

				// x没有父节点 => x是根节点

				x.red = false; // 根节点必须是黑色
				return x;
			} else if (x.red) {

				// x是红色(一个可能的场景是:被删除的节点有一个右孩子)

				x.red = false; // 把x设为黑色,不需调整
				return root;
			}

			// x是黑色

			else if ((xpl = xp.left) == x) {

				// x是父节点的左孩子

				if ((xpr = xp.right) != null && xpr.red) {

					// x的兄弟节点是红色 => 父节点是黑色,交换父节点和兄弟节点的颜色,对父节点进行左旋操作

					xpr.red = false;
					xp.red = true;
					root = rotateLeft(root, xp);
					xpr = (xp = x.parent) == null ? null : xp.right;
				}

				/* 往下的逻辑:x的兄弟节点是黑色 */

				if (xpr == null)

					// x的兄弟节点不存在 => 这是什么情况?

					x = xp;
				else {

					// x的兄弟节点存在且是黑色

					TreeNode<K, V> sl = xpr.left, sr = xpr.right;
					if ((sr == null || !sr.red) && (sl == null || !sl.red)) {

						// x的兄弟节点有两个黑色孩子

						xpr.red = true;
						x = xp;
					} else {

						// x的兄弟节点有红色孩子

						if (sr == null || !sr.red) {

							// LR转RR

							if (sl != null)
								sl.red = false;
							xpr.red = true;
							root = rotateRight(root, xpr);
							xpr = (xp = x.parent) == null ? null : xp.right;
						}

						/* 往下的逻辑:RR */

						// 变色,左旋

						if (xpr != null) {
							xpr.red = (xp == null) ? false : xp.red;
							if ((sr = xpr.right) != null)
								sr.red = false;
						}

						if (xp != null) {
							xp.red = false;
							root = rotateLeft(root, xp);
						}

						x = root;
					}
				}
			} else { // symmetric

				// x是父节点的右孩子

				if (xpl != null && xpl.red) {
					xpl.red = false;
					xp.red = true;
					root = rotateRight(root, xp);
					xpl = (xp = x.parent) == null ? null : xp.left;
				}
				if (xpl == null)
					x = xp;
				else {
					TreeNode<K, V> sl = xpl.left, sr = xpl.right;
					if ((sl == null || !sl.red) && (sr == null || !sr.red)) {
						xpl.red = true;
						x = xp;
					} else {
						if (sl == null || !sl.red) {
							if (sr != null)
								sr.red = false;
							xpl.red = true;
							root = rotateLeft(root, xpl);
							xpl = (xp = x.parent) == null ? null : xp.left;
						}
						if (xpl != null) {
							xpl.red = (xp == null) ? false : xp.red;
							if ((sl = xpl.left) != null)
								sl.red = false;
						}
						if (xp != null) {
							xp.red = false;
							root = rotateRight(root, xp);
						}
						x = root;
					}
				}
			}
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值