1. public V put(K key, V value) {
    2. Entry<K,V> t = root;
    3. /**
    4. * 如果根节点都为null,还没建立起来红黑树,我们先new Entry并赋值给root把红黑树建立起来,这个时候红
    5. * 黑树中已经有一个节点了,同时修改操作+1。
    6. */
    7. if (t == null) {
    8. compare(key, key); // type (and possibly null) check
    9. root = new Entry<>(key, value, null);
    10. size = 1;
    11. modCount++;
    12. return null;
    13. }
    14. /**
    15. * 如果节点不为null,定义一个cmp,这个变量用来进行二分查找时的比较;定义parent,是new Entry时必须
    16. * 要的参数
    17. */
    18. int cmp;
    19. Entry<K,V> parent;
    20. // split comparator and comparable paths
    21. Comparator<? super K> cpr = comparator;
    22. if (cpr != null) {
    23. /**
    24. * 从root节点开始遍历,通过二分查找逐步向下找
    25. * 第一次循环:从根节点开始,这个时候parent就是根节点,然后通过自定义的排序算法
    26. * cpr.compare(key, t.key)比较传入的key和根节点的key值,如果传入的key<root.key,那么
    27. * 继续在root的左子树中找,从root的左孩子节点(root.left)开始:如果传入的key>root.key,
    28. * 那么继续在root的右子树中找,从root的右孩子节点(root.right)开始;如果恰好key==root.key,
    29. * 那么直接根据root节点的value值即可。
    30. * 后面的循环规则一样,当遍历到的当前节点作为起始节点,逐步往下找
    31. *
    32. * 需要注意的是:这里并没有对key是否为null进行判断,建议自己的实现Comparator时应该要考虑在内
    33. */
    34. do {
    35. parent = t;
    36. cmp = cpr.compare(key, t.key);
    37. if (cmp < 0)
    38. t = t.left;
    39. else if (cmp > 0)
    40. t = t.right;
    41. else
    42. return t.setValue(value); // 此时不会执行modCount++? modCount只是记录红黑树结构调整了多少次
    43. } while (t != null); //当t == null时 说明已经遍历完左子树或右子树,此时parent指向待插入元素的父亲节点
    44. }
    45. else { //使用默认的比较规则,也就是key 的compareTo方法,注意key的类要实现Comparable接口
    46. //从这里看出,当默认排序时,key值是不能为null的
    47. if (key == null)
    48. throw new NullPointerException();
    49. @SuppressWarnings("unchecked")
    50. Comparable<? super K> k = (Comparable<? super K>) key;
    51. do {
    52. parent = t;
    53. cmp = k.compareTo(t.key);
    54. if (cmp < 0)
    55. t = t.left;
    56. else if (cmp > 0)
    57. t = t.right;
    58. else
    59. return t.setValue(value);
    60. } while (t != null);
    61. }
    62. /**
    63. * 能执行到这里,说明前面并没有找到相同的key,节点已经遍历到最后了,我们只需要new一个Entry放到
    64. * parent下面即可,但放到左子节点上还是右子节点上,就需要按照红黑树的规则来。
    65. */
    66. Entry<K,V> e = new Entry<>(key, value, parent);
    67. if (cmp < 0)
    68. parent.left = e;
    69. else
    70. parent.right = e;
    71. /**
    72. * 节点加进去了,并不算完,会对红黑树的结构造成
    73. * 破坏,我们需要通过一些操作来进行自动平衡处置,如【变色】【左旋】【右旋】
    74. */
    75. fixAfterInsertion(e);
    76. size++;
    77. modCount++;
    78. return null;
    79. }
    1. private void fixAfterInsertion(Entry<K,V> x) {
    2. x.color = RED;
    3. while (x != null && x != root && x.parent.color == RED) {
    4. if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { // 如果父亲节点在爷爷节点的左边
    5. Entry<K,V> y = rightOf(parentOf(parentOf(x))); // y为叔叔节点
    6. if (colorOf(y) == RED) { // 如果叔叔节点是红色
    7. setColor(parentOf(x), BLACK); // 将父亲节点和叔叔节点设为黑色,爷爷节点设为红色
    8. setColor(y, BLACK);
    9. setColor(parentOf(parentOf(x)), RED);
    10. x = parentOf(parentOf(x));
    11. } else {
    12. if (x == rightOf(parentOf(x))) { //如果x为父节点的右子节点
    13. x = parentOf(x); 左旋
    14. rotateLeft(x);
    15. }
    16. setColor(parentOf(x), BLACK);
    17. setColor(parentOf(parentOf(x)), RED);
    18. rotateRight(parentOf(parentOf(x)));
    19. }
    20. } else {
    21. Entry<K,V> y = leftOf(parentOf(parentOf(x)));
    22. if (colorOf(y) == RED) {
    23. setColor(parentOf(x), BLACK);
    24. setColor(y, BLACK);
    25. setColor(parentOf(parentOf(x)), RED);
    26. x = parentOf(parentOf(x));
    27. } else {
    28. if (x == leftOf(parentOf(x))) {
    29. x = parentOf(x);
    30. rotateRight(x);
    31. }
    32. setColor(parentOf(x), BLACK);
    33. setColor(parentOf(parentOf(x)), RED);
    34. rotateLeft(parentOf(parentOf(x)));
    35. }
    36. }
    37. }
    38. root.color = BLACK;
    39. }

    原文链接:https://blog.csdn.net/weixin_37576193/article/details/107783584