zy19982004--容器学习五:TreeMap源码分析

一.TreeMap成员变量

Java代码   收藏代码
  1. //Comparator比较器接口,接口里面只有两个方法int compare(T o1, T o2);boolean equals(Object obj);  
  2. private final Comparator<? super K> comparator;  
  3.   
  4. //根节点  
  5. private transient Entry<K,V> root = null;  
  6.   
  7. private transient int size = 0;  
  8. private transient int modCount = 0;  

 

二.TreeMap的Entry对象

Java代码   收藏代码
  1. static final class Entry<K,V> implements Map.Entry<K,V> {  
  2.         //构成树的三个属性left,left,parent  
  3.         K key;  
  4.         V value;  
  5.         Entry<K,V> left = null;  
  6.         Entry<K,V> right = null;  
  7.         Entry<K,V> parent;  
  8.         boolean color = BLACK;    //该节点红色还是黑色  
  9.     }  

 

三.构造函数

Java代码   收藏代码
  1. //默认构造函数时comparator为空,则插入到TreeMap里面的key必须实现Comparator接口  
  2. public TreeMap() {  
  3.     comparator = null;  
  4. }  
  5.   
  6. //用户指定Comparator  
  7. public TreeMap(Comparator<? super K> comparator) {  
  8.     this.comparator = comparator;  
  9. }  

 

四.取数据

Java代码   收藏代码
  1.    public V get(Object key) {  
  2.        Entry<K,V> p = getEntry(key);  
  3.        return (p==null ? null : p.value);  
  4.    }  
  5.      
  6.    final Entry<K,V> getEntry(Object key) {  
  7.        //如果用户指定了Comparable,用指定的  
  8.        if (comparator != null)  
  9.            return getEntryUsingComparator(key);  
  10.        //get操作key不能为空  
  11.        if (key == null)  
  12.            throw new NullPointerException();  
  13.    //如果用户没指定Comparable,用key作为Comparable  
  14. Comparable<? super K> k = (Comparable<? super K>) key;  
  15.        Entry<K,V> p = root;  
  16.        //以根节点当前节点开始遍历搜索  
  17.        while (p != null) {  
  18.         //拿被检索的节点的值和当前节点的值比较  
  19.            int cmp = k.compareTo(p.key);  
  20.            //如果被检索的节点的值更小,则以当前节点的左子节点作为新的当前节点。  
  21.            if (cmp < 0)  
  22.                p = p.left;  
  23.            //如果被检索的节点的值更大,则以当前节点的右子节点作为新的当前节点。  
  24.            else if (cmp > 0)  
  25.                p = p.right;  
  26.            //被检索的节点的值和当前节点的值相等,则是我们需要的节点  
  27.            else  
  28.                return p;  
  29.        }  
  30.        //找不到返回null  
  31.        return null;  
  32.    }  
  33.      
  34.    //和上面逻辑一样  
  35.    final Entry<K,V> getEntryUsingComparator(Object key) {  
  36.     K k = (K) key;  
  37.            Comparator<? super K> cpr = comparator;  
  38.            if (cpr != null) {  
  39.                Entry<K,V> p = root;  
  40.                while (p != null) {  
  41.                    int cmp = cpr.compare(k, p.key);  
  42.                    if (cmp < 0)  
  43.                        p = p.left;  
  44.                    else if (cmp > 0)  
  45.                        p = p.right;  
  46.                    else  
  47.                        return p;  
  48.                }  
  49.            }  
  50.            return null;  
  51.        }  

 

五.存数据

Java代码   收藏代码
  1. //返回被新节点覆盖的节点的值,不存在被覆盖的节点返回null  
  2.     public V put(K key, V value) {  
  3.         Entry<K,V> t = root;  
  4.         if (t == null) {  
  5.         // TBD:  
  6.         // 5045147: (coll) Adding null to an empty TreeSet should  
  7.         // throw NullPointerException  
  8.         //  
  9.         // compare(key, key); // type check  
  10.             //第一次插入节点  
  11.             root = new Entry<K,V>(key, value, null);  
  12.             size = 1;  
  13.             modCount++;  
  14.             return null;  
  15.         }  
  16.         int cmp;  
  17.         Entry<K,V> parent;  
  18.         // split comparator and comparable paths  
  19.         Comparator<? super K> cpr = comparator;  
  20.         //用指定的Comparator  
  21.         if (cpr != null) {  
  22.             //以根节点当前节点t开始搜索,拿被添加的节点的值和当前节点的值比较。  
  23.             do {  
  24.                 //刚开始parent=t  
  25.                 parent = t;  
  26.                 cmp = cpr.compare(key, t.key);  
  27.                 //如果被添加的节点的值更小,则以当前节点的左子节点作为新的当前节点,此时t=pL  
  28.                 if (cmp < 0)  
  29.                     t = t.left;  
  30.                 //如果被添加的节点的值更大,则以当前节点的右子节点作为新的当前节点,此时t=pR  
  31.                 else if (cmp > 0)  
  32.                     t = t.right;  
  33.                 //如果相等,直接覆盖  
  34.                 else  
  35.                     return t.setValue(value);  
  36.             } while (t != null); //直到新的当前节点为空  
  37.         }  
  38.         else {  
  39.             //put操作key不能为空  
  40.             if (key == null)  
  41.                 throw new NullPointerException();  
  42.             //用key作为Comparator,下同  
  43.             Comparable<? super K> k = (Comparable<? super K>) key;  
  44.             do {  
  45.                 parent = t;  
  46.                 cmp = k.compareTo(t.key);  
  47.                 if (cmp < 0)  
  48.                     t = t.left;  
  49.                 else if (cmp > 0)  
  50.                     t = t.right;  
  51.                 else  
  52.                     return t.setValue(value);  
  53.             } while (t != null);  
  54.         }  
  55.         //生成一个新节点,父亲为parent  
  56.         Entry<K,V> e = new Entry<K,V>(key, value, parent);  
  57.         //根据最后一次比较的cmp确定pL位置存放e还是pR存放e  
  58.         if (cmp < 0)  
  59.             parent.left = e;  
  60.         else  
  61.             parent.right = e;  
  62.         //修复红黑树  
  63.         fixAfterInsertion(e);  
  64.         size++;  
  65.         modCount++;  
  66.         //插入一个新节点时返回null  
  67.         return null;  
  68.     }  

 

六.删数据

Java代码   收藏代码
  1. public V remove(Object key) {  
  2.     //先找到节点,getEntry(key)key不能为空,所以remove方法key不能为空  
  3.     Entry<K,V> p = getEntry(key);  
  4.     if (p == null)  
  5.         return null;  
  6.   
  7.     //保留一个节点的值  
  8.     V oldValue = p.value;  
  9.     //删除节点  
  10.     deleteEntry(p);  
  11.     return oldValue;  
  12. }  
  13.   
  14. private void deleteEntry(Entry<K,V> p) {  
  15.     modCount++;  
  16.     size--;  
  17.   
  18.     //若被删除节点 p 的左、右子树均非空  
  19.     if (p.left != null && p.right != null) {  
  20.         //得到p节点的中序后继s  
  21.         Entry<K,V> s = successor (p);  
  22.         //用s替代p  
  23.         p.key = s.key;  
  24.         p.value = s.value;  
  25.         p = s;  
  26.     }   
  27.   
  28.     //如果p节点的左节点存在,replacement代表左节点,否则代表右节点  
  29.     Entry<K,V> replacement = (p.left != null ? p.left : p.right);  
  30.   
  31.     if (replacement != null) {  
  32.         replacement.parent = p.parent;  
  33.         // 如果 p 没有父节点,则 replacemment 变成父节点  
  34.         if (p.parent == null)  
  35.             root = replacement;  
  36.         // 如果 p 节点是其父节点的左子节点  
  37.         else if (p == p.parent.left)  
  38.             p.parent.left  = replacement;  
  39.         // 如果 p 节点是其父节点的右子节点  
  40.         else  
  41.             p.parent.right = replacement;  
  42.   
  43.         p.left = p.right = p.parent = null;  
  44.   
  45.         // Fix replacement  
  46.         if (p.color == BLACK)  
  47.              // 修复红黑树  
  48.             fixAfterDeletion(replacement);  
  49.      // 如果 p 节点没有父节点  
  50.     } else if (p.parent == null) { // return if we are the only node.  
  51.         root = null;  
  52.     } else { //  No children. Use self as phantom replacement and unlink.  
  53.         if (p.color == BLACK)  
  54.             // 修复红黑树  
  55.             fixAfterDeletion(p);  
  56.   
  57.         if (p.parent != null) {  
  58.             // 如果 p 是其父节点的左子节点  
  59.             if (p == p.parent.left)  
  60.                 p.parent.left = null;  
  61.             // 如果 p 是其父节点的右子节点  
  62.             else if (p == p.parent.right)  
  63.                 p.parent.right = null;  
  64.             p.parent = null;  
  65.         }  
  66.     }  
  67. }  

 

七.containsKey containsValue方法

Java代码   收藏代码
  1. public boolean containsKey(Object key) {  
  2.         return getEntry(key) != null;  
  3.     }  
  4.   
  5.     //按中序遍历节点的顺序,把节点和指定value比较  
  6.     public boolean containsValue(Object value) {  
  7.         for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))  
  8.             if (valEquals(value, e.value))  
  9.                 return true;  
  10.         return false;  
  11.     }  
  12.   
  13.   
  14. static final class Entry<K,V> implements Map.Entry<K,V> {  
  15.     //找到最小的节点  
  16.     final Entry<K,V> getFirstEntry() {  
  17.         Entry<K,V> p = root;  
  18.         if (p != null)  
  19.             while (p.left != null)  
  20.                 p = p.left;  
  21.         return p;  
  22.     }  
  23.   
  24.     //找到最大的节点  
  25.     final Entry<K,V> getLastEntry() {  
  26.         Entry<K,V> p = root;  
  27.         if (p != null)  
  28.             while (p.right != null)  
  29.                 p = p.right;  
  30.         return p;  
  31.     }  
  32. }  
  33.  //找到指定节点的后继节点  
  34. static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {  
  35.         if (t == null)  
  36.             return null;  
  37.         //如果t有右子数  
  38.         else if (t.right != null) {  
  39.             Entry<K,V> p = t.right;  
  40.             //tRL不为空,tRL就是t的直接后继;tRLL不为空,tRLL就是t的直接后继......  
  41.             while (p.left != null)  
  42.                 p = p.left;  
  43.             return p;  
  44.         //如果t只有左子数  
  45.         } else {  
  46.             //如果t=pL,直接返回p  
  47.             //如果t=pR,返回p.parent  
  48.             Entry<K,V> p = t.parent;  
  49.             Entry<K,V> ch = t;  
  50.             while (p != null && ch == p.right) {  
  51.                 ch = p;  
  52.                 p = p.parent;  
  53.             }  
  54.             return p;  
  55.         }  
  56. }  
  57.   
  58. //找到指定节点的前驱节点  
  59. static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {  
  60.         if (t == null)  
  61.             return null;  
  62.         //如果t有左子数  
  63.         else if (t.left != null) {  
  64.             Entry<K,V> p = t.left;  
  65.             //tLR不为空,tLR就是t的直接后继;tLRR不为空,tLRR就是t的直接后继......  
  66.             while (p.right != null)  
  67.                 p = p.right;  
  68.             return p;  
  69.         } else {  
  70.             //如果t=pR,直接返回p  
  71.             //如果t=pL,返回p.parent  
  72.             Entry<K,V> p = t.parent;  
  73.             Entry<K,V> ch = t;  
  74.             while (p != null && ch == p.left) {  
  75.                 ch = p;  
  76.                 p = p.parent;  
  77.             }  
  78.             return p;  
  79.         }  
  80. }  

 

八.fixAfterInsertion方法

Java代码   收藏代码
  1.   // 插入节点后修复红黑树  
  2. private void fixAfterInsertion(Entry<K,V> x)  
  3. {  
  4.  x.color = RED;  
  5.  // 直到 x 节点的父节点不是根,且 x 的父节点不是红色  
  6.  while (x != null && x != root  
  7.    && x.parent.color == RED)  
  8.  {  
  9.    // 如果 x 的父节点是其父节点的左子节点  
  10.    if (parentOf(x) == leftOf(parentOf(parentOf(x))))  
  11.    {  
  12.      // 获取 x 的父节点的兄弟节点  
  13.      Entry<K,V> y = rightOf(parentOf(parentOf(x)));  
  14.      // 如果 x 的父节点的兄弟节点是红色  
  15.      if (colorOf(y) == RED)  
  16.      {  
  17.        // 将 x 的父节点设为黑色  
  18.        setColor(parentOf(x), BLACK);  
  19.        // 将 x 的父节点的兄弟节点设为黑色  
  20.        setColor(y, BLACK);  
  21.        // 将 x 的父节点的父节点设为红色  
  22.        setColor(parentOf(parentOf(x)), RED);  
  23.        x = parentOf(parentOf(x));  
  24.      }  
  25.      // 如果 x 的父节点的兄弟节点是黑色  
  26.      else  
  27.      {  
  28.        // 如果 x 是其父节点的右子节点  
  29.        if (x == rightOf(parentOf(x)))  
  30.        {  
  31.          // 将 x 的父节点设为 x  
  32.          x = parentOf(x);  
  33.          rotateLeft(x);  
  34.        }  
  35.        // 把 x 的父节点设为黑色  
  36.        setColor(parentOf(x), BLACK);  
  37.        // 把 x 的父节点的父节点设为红色  
  38.        setColor(parentOf(parentOf(x)), RED);  
  39.        rotateRight(parentOf(parentOf(x)));  
  40.      }  
  41.    }  
  42.    // 如果 x 的父节点是其父节点的右子节点  
  43.    else  
  44.    {  
  45.      // 获取 x 的父节点的兄弟节点  
  46.      Entry<K,V> y = leftOf(parentOf(parentOf(x)));  
  47.      // 如果 x 的父节点的兄弟节点是红色  
  48.      if (colorOf(y) == RED)  
  49.      {  
  50.        // 将 x 的父节点设为黑色。  
  51.        setColor(parentOf(x), BLACK);  
  52.        // 将 x 的父节点的兄弟节点设为黑色  
  53.        setColor(y, BLACK);  
  54.        // 将 x 的父节点的父节点设为红色  
  55.        setColor(parentOf(parentOf(x)), RED);  
  56.        // 将 x 设为 x 的父节点的节点  
  57.        x = parentOf(parentOf(x));  
  58.      }  
  59.      // 如果 x 的父节点的兄弟节点是黑色  
  60.      else  
  61.      {  
  62.        // 如果 x 是其父节点的左子节点  
  63.        if (x == leftOf(parentOf(x)))  
  64.        {  
  65.          // 将 x 的父节点设为 x  
  66.          x = parentOf(x);  
  67.          rotateRight(x);  
  68.        }  
  69.        // 把 x 的父节点设为黑色  
  70.        setColor(parentOf(x), BLACK);  
  71.        // 把 x 的父节点的父节点设为红色  
  72.        setColor(parentOf(parentOf(x)), RED);  
  73.        rotateLeft(parentOf(parentOf(x)));  
  74.      }  
  75.    }  
  76.  }  
  77.  // 将根节点设为黑色  
  78.  root.color = BLACK;  
  79. }  

 

 

九.fixAfterDeletion方法

Java代码   收藏代码
  1.   // 删除节点后修复红黑树  
  2. private void fixAfterDeletion(Entry<K,V> x)  
  3. {  
  4.  // 直到 x 不是根节点,且 x 的颜色是黑色  
  5.  while (x != root && colorOf(x) == BLACK)  
  6.  {  
  7.    // 如果 x 是其父节点的左子节点  
  8.    if (x == leftOf(parentOf(x)))  
  9.    {  
  10.      // 获取 x 节点的兄弟节点  
  11.      Entry<K,V> sib = rightOf(parentOf(x));  
  12.      // 如果 sib 节点是红色  
  13.      if (colorOf(sib) == RED)  
  14.      {  
  15.        // 将 sib 节点设为黑色  
  16.        setColor(sib, BLACK);  
  17.        // 将 x 的父节点设为红色  
  18.        setColor(parentOf(x), RED);  
  19.        rotateLeft(parentOf(x));  
  20.        // 再次将 sib 设为 x 的父节点的右子节点  
  21.        sib = rightOf(parentOf(x));  
  22.      }  
  23.      // 如果 sib 的两个子节点都是黑色  
  24.      if (colorOf(leftOf(sib)) == BLACK  
  25.        && colorOf(rightOf(sib)) == BLACK)  
  26.      {  
  27.        // 将 sib 设为红色  
  28.        setColor(sib, RED);  
  29.        // 让 x 等于 x 的父节点  
  30.        x = parentOf(x);  
  31.      }  
  32.      else  
  33.      {  
  34.        // 如果 sib 的只有右子节点是黑色  
  35.        if (colorOf(rightOf(sib)) == BLACK)  
  36.        {  
  37.          // 将 sib 的左子节点也设为黑色  
  38.          setColor(leftOf(sib), BLACK);  
  39.          // 将 sib 设为红色  
  40.          setColor(sib, RED);  
  41.          rotateRight(sib);  
  42.          sib = rightOf(parentOf(x));  
  43.        }  
  44.        // 设置 sib 的颜色与 x 的父节点的颜色相同  
  45.        setColor(sib, colorOf(parentOf(x)));  
  46.        // 将 x 的父节点设为黑色  
  47.        setColor(parentOf(x), BLACK);  
  48.        // 将 sib 的右子节点设为黑色  
  49.        setColor(rightOf(sib), BLACK);  
  50.        rotateLeft(parentOf(x));  
  51.        x = root;  
  52.      }  
  53.    }  
  54.    // 如果 x 是其父节点的右子节点  
  55.    else  
  56.    {  
  57.      // 获取 x 节点的兄弟节点  
  58.      Entry<K,V> sib = leftOf(parentOf(x));  
  59.      // 如果 sib 的颜色是红色  
  60.      if (colorOf(sib) == RED)  
  61.      {  
  62.        // 将 sib 的颜色设为黑色  
  63.        setColor(sib, BLACK);  
  64.        // 将 sib 的父节点设为红色  
  65.        setColor(parentOf(x), RED);  
  66.        rotateRight(parentOf(x));  
  67.        sib = leftOf(parentOf(x));  
  68.      }  
  69.      // 如果 sib 的两个子节点都是黑色  
  70.      if (colorOf(rightOf(sib)) == BLACK  
  71.        && colorOf(leftOf(sib)) == BLACK)  
  72.      {  
  73.        // 将 sib 设为红色  
  74.        setColor(sib, RED);  
  75.        // 让 x 等于 x 的父节点  
  76.        x = parentOf(x);  
  77.      }  
  78.      else  
  79.      {  
  80.        // 如果 sib 只有左子节点是黑色  
  81.        if (colorOf(leftOf(sib)) == BLACK)  
  82.        {  
  83.          // 将 sib 的右子节点也设为黑色  
  84.          setColor(rightOf(sib), BLACK);  
  85.          // 将 sib 设为红色  
  86.          setColor(sib, RED);  
  87.          rotateLeft(sib);  
  88.          sib = leftOf(parentOf(x));  
  89.        }  
  90.        // 将 sib 的颜色设为与 x 的父节点颜色相同  
  91.        setColor(sib, colorOf(parentOf(x)));  
  92.        // 将 x 的父节点设为黑色  
  93.        setColor(parentOf(x), BLACK);  
  94.        // 将 sib 的左子节点设为黑色  
  95.        setColor(leftOf(sib), BLACK);  
  96.        rotateRight(parentOf(x));  
  97.        x = root;  
  98.      }  
  99.    }  
  100.  }  
  101.  setColor(x, BLACK);  
  102. }  

 

十.迭代

Java代码   收藏代码
  1. /** 
  2.      * Base class for TreeMap Iterators 
  3.      */  
  4.     abstract class PrivateEntryIterator<T> implements Iterator<T> {  
  5.         Entry<K,V> next;  
  6.         Entry<K,V> lastReturned;  
  7.         int expectedModCount;  
  8.   
  9.         PrivateEntryIterator(Entry<K,V> first) {  
  10.             expectedModCount = modCount;  
  11.             lastReturned = null;  
  12.             next = first;  
  13.         }  
  14.         //后继迭代  
  15.     final Entry<K,V> nextEntry() {  
  16.             Entry<K,V> e = next;  
  17.             if (e == null)  
  18.                 throw new NoSuchElementException();  
  19.             if (modCount != expectedModCount)  
  20.                 throw new ConcurrentModificationException();  
  21.   
  22.             next = successor(e);  
  23.             lastReturned = e;  
  24.             return e;  
  25.         }  
  26.   
  27.         //前驱迭代  
  28.         final Entry<K,V> prevEntry() {  
  29.             Entry<K,V> e = next;  
  30.             if (e == null)  
  31.                 throw new NoSuchElementException();  
  32.             if (modCount != expectedModCount)  
  33.                 throw new ConcurrentModificationException();  
  34.             next = predecessor(e);  
  35.             lastReturned = e;  
  36.             return e;  
  37.         }  
  38.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值