Java-Collection源码分析(十三)——TreeMap

TreeMap采用了红黑树的数据结构。

一、红黑树

红黑树是一个二叉搜索树,它在每个节点上增加了一个存储位来表示节点颜色,可以是RED或BLACK。红黑树的本质还是二叉树。由二叉树进化为2-3树或者是2-3-4树,然后再进化为红黑树,接下来将《算法导论》和《算法(第四版)》中的红黑树进行对比。

《算法导论》中规则:

(1)、每个节点都只能是红色或者黑色;

(2)、根节点是黑色;

(3)、每个叶节点(NIL节点,空节点)是黑色的;

(4)、如果一个结点是红的,则它两个子节点都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点;

(5)、从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

《算法(第四版)》中的规则:

将3-结点表示为一条左斜的红色链接(两2-结点其中之一是另一个的左子结点)相连的两个2-结点。黑链接则为普通链接。

(1)、红连接均为左链接;

(2)、没有任何一个结点同时和两条红链接相连;

(3)、该树是完美黑色平衡的,即任意空链接到根节点的路径上的黑链接数量相同。





在TreeMap中定义的数据结点及一些基本操作:

    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK;

        //使用给定的键,值和父结点,以及null子链接和BLACK颜色创建一个新单元格。
        Entry(K key, V value, Entry<K,V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
        }

        //返回key
        public K getKey() {
            return key;
        }

        //返回与该key关联的value
        public V getValue() {
            return value;
        }

        //将当前与key相关联的value替换为给定value
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
        }

        public int hashCode() {
            int keyHash = (key==null ? 0 : key.hashCode());
            int valueHash = (value==null ? 0 : value.hashCode());
            return keyHash ^ valueHash;
        }

        public String toString() {
            return key + "=" + value;
        }
    }

    //返回TreeMap中的第一个结点(根据TreeMap的key排序功能)。 如果TreeMap为空,则返回null。
    final Entry<K,V> getFirstEntry() {
        Entry<K,V> p = root;
        //通过一直查找左结点找到第一个结点
        if (p != null)
            while (p.left != null)
                p = p.left;
        return p;
    }

    //返回TreeMap中的最后一个结点(根据TreeMap的key排序功能)。 如果TreeMap为空,则返回null。
    final Entry<K,V> getLastEntry() {
        Entry<K,V> p = root;
        //通过一直查找右结点找到最后一个结点
        if (p != null)
            while (p.right != null)
                p = p.right;
        return p;
    }

    //返回指定的结点的后继结点,如果没有,则返回null。
    static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
    		//如果指定结点为null,则返回null
        if (t == null)
            return null;
        //如果指定结点的右结点不为null,则查找右子树的第一个结点
        else if (t.right != null) {
            Entry<K,V> p = t.right;
            while (p.left != null)
                p = p.left;
            return p;
        } else {
        		//如果右结点为null
            Entry<K,V> p = t.parent;
            Entry<K,V> ch = t;
            //如果指定结点为父结点的右结点,则一直查找父结点,
            //向上查找,直到出现某结点为父结点的左结点为止,此时返回此结点的父结点
            //否则一直查找向上查找,直到返回null
            while (p != null && ch == p.right) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

    //返回指定Entry的前续结点,如果没有,则返回null。
    static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
    		//如果指定结点为null,则返回null
        if (t == null)
            return null;
        //如果指定结点的左结点不为null,则查找其左子树的左后一个结点
        else if (t.left != null) {
            Entry<K,V> p = t.left;
            while (p.right != null)
                p = p.right;
            return p;
        } else {
        		//如果指定结点的左结点为null
            Entry<K,V> p = t.parent;
            Entry<K,V> ch = t;
            //如果指定结点为父结点的左结点,则一直查找父结点,
            //向上查找,直到出现某结点为父结点的右结点为止,此时返回此结点的父结点
            //否则一直查找向上查找,直到返回null
            while (p != null && ch == p.left) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

二、TreeMap中红黑树的插入和删除操作

2.1 树结点的旋转操作

以4为中心右移,以2为中心左移



左旋转代码:

    //左旋转
    private void rotateLeft(Entry<K,V> p) {
        if (p != null) {
            Entry<K,V> r = p.right;
            //旋转后,将p与p.right.left相关联
            p.right = r.left;
            if (r.left != null)
                r.left.parent = p;
            //r(p.right)代替p的位置    
            r.parent = p.parent;
            if (p.parent == null)
                root = r;
            else if (p.parent.left == p)
                p.parent.left = r;
            else
                p.parent.right = r;
                
            //p与r(原来的p.right)重新关联
            r.left = p;
            p.parent = r;
        }
    }
右旋转代码:

    //右旋转
    private void rotateRight(Entry<K,V> p) {
        if (p != null) {
            Entry<K,V> l = p.left;
            //旋转后,将p与p.left.right相关联
            p.left = l.right;
            if (l.right != null) l.right.parent = p;
            	
            //l(p.left)替换p的位置
            l.parent = p.parent;
            if (p.parent == null)
                root = l;
            else if (p.parent.right == p)
                p.parent.right = l;
            else p.parent.left = l;
            	
            //p与l(原来的p.left)重新关联
            l.right = p;
            p.parent = l;
        }
    }

2.2 结点的插入操作

2.2.1 插入操作的源代码

    //将指定的value与此映射中的指定key相关联。 如果map先前包含了该key的映射,则替换旧值。
    public V put(K key, V value) {
    		//定义t为根结点
        Entry<K,V> t = root;
        //如果t表示一个空树
        if (t == null) {
            compare(key, key); //类型(可能为null)检查
            //将该结点设置为根结点root
            root = new Entry<>(key, value, null);
            //将容器的大小+1
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        //定义父结点
        Entry<K,V> parent;
        //拆分比较器和可比路径
        //指定排序算法
        Comparator<? super K> cpr = comparator;
        //如果cpr不为空,使用指定的排序算法
        if (cpr != null) {
            do {
            		//经过循环之后,t往下移动为要插入结点的位置,parent为指向上一次t的位置,为t的父结点
                parent = t;
                //比较新增结点的key值与当前结点t的key值大小
                cmp = cpr.compare(key, t.key);
                //从上往下进行查找新增结点的位置,直到将t是叶结点
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        //如果cpr为空,只用默认的排序算法,分析同上
        else {
        		//如果key为空,报错
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        //创建新结点,并将parent作为父结点
        Entry<K,V> e = new Entry<>(key, value, parent);
        //将父结点与新增结点进行关联
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        //插入结点时候,对红黑树进行调整
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

2.2.2 插入后的树结构调整

原理:分为三种情况

情况1:如果x的叔结点为RED



情况2:叔结点为黑色,x为右孩子


情况3:叔结点为黑色,x为左孩子



代码分析:

   //新增结点之后的调整修复操作
    private void fixAfterInsertion(Entry<K,V> x) {
        x.color = RED;
				//循环,直到x不是根结点,并且父结点不为红色
				//父结点为红色违背性质四
        while (x != null && x != root && x.parent.color == RED) {
        		//x的父结点为左结点
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
            		//定义y为x的右叔结点
                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                //如果x的叔结点为RED:情况一
                if (colorOf(y) == RED) {
                		//将x的父结点设置为黑色
                    setColor(parentOf(x), BLACK);
                    //将x的叔结点设置为黑色
                    setColor(y, BLACK);
                    //将x的父结点的父结点设置为红色
                    setColor(parentOf(parentOf(x)), RED);
                    //将x指向自己的父结点的父结点
                    x = parentOf(parentOf(x));
                } else {	//x的叔结点y为黑色,情况2和情况3
                		//情况2:叔结点为黑色,x为右孩子,则以x的父节点为中心进行左旋转,将情况2转变成情况3
                    if (x == rightOf(parentOf(x))) {
                    		//将x指向自己的父结点
                        x = parentOf(x);
                        //左旋转
                        rotateLeft(x);
                    }
                    //情况3;叔结点为黑色,x为左孩子
                    //如果x为左结点,则将x的父结点颜色设置为黑色
                    setColor(parentOf(x), BLACK);
                    //将x的父结点的父结点的颜色设置为红色
                    setColor(parentOf(parentOf(x)), RED);
                    //以x的父结点的父结点为中心进行右旋转
                    rotateRight(parentOf(parentOf(x)));
                }
            } else {
            		//定义y为x的左叔结点,分析同上
                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    x = parentOf(parentOf(x));
                } else {
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rotateRight(x);
                    }
                    setColor(parentOf(x), BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    rotateLeft(parentOf(parentOf(x)));
                }
            }
        }
        root.color = BLACK;
    }

2.3 删除结点操作

2.3.1 删除操作源码

    //删除结点p
    private void deleteEntry(Entry<K,V> p) {
        modCount++;
        size--;

        // 如果删除指定结点p的左子树和右子树不为空(或者p有两个子结点),则将p替换为该后继结点
        if (p.left != null && p.right != null) {
            Entry<K,V> s = successor(p);
            p.key = s.key;
            p.value = s.value;
            p = s;
        }
        
        //开始修复替换结点(如果存在)。
        Entry<K,V> replacement = (p.left != null ? p.left : p.right);

        if (replacement != null) {
            //将替换结点连接到y的父结点
            replacement.parent = p.parent;
            //如果p的父结点为null,即p为根结点,则替换结点这是为根结点
            if (p.parent == null)
                root = replacement;
            else if (p == p.parent.left)	//如果p为左子结点,则将y父结点的左结点连接到替换结点
                p.parent.left  = replacement;
            else		//如果p为右子结点,则将y父结点的右结点连接到替换结点
                p.parent.right = replacement;

            //取消p的链接,交给GC回收。
            p.left = p.right = p.parent = null;

            //如果p的结点颜色为黑色,对红黑树进行调整
            if (p.color == BLACK)
                fixAfterDeletion(replacement);
        } else if (p.parent == null) {	//此时p为唯一结点
            root = null;
        } else { 	//p没有子结点,即p为叶结点
            if (p.color == BLACK)		//如果P结点的颜色为黑色,对红黑树进行调整
                fixAfterDeletion(p);
						
						//将取消p与父结点的连接
            if (p.parent != null) {
                if (p == p.parent.left)
                    p.parent.left = null;
                else if (p == p.parent.right)
                    p.parent.right = null;
                p.parent = null;
            }
        }
    }

2.3.2 删除结点后的树结构的调整

原理:分为三种情况

情况1:x的兄弟结点sib为红色


情况2:指定结点x的兄弟结点sib是黑色结点,而且sib的两个子结点都是黑色结点


情况3:指定结点x的兄弟结点sib是黑色结点,sib的右结点为黑色结点,左结点为红色结点


情况4:指定结点x的兄弟结点sib为黑色结点,sib的右结点为红色结点


调整操作的源代码:

    // 删除完结点后,就要根据情况来对红黑树进行调整
    private void fixAfterDeletion(Entry<K,V> x) {
    		//指定结点不是根结点,并且结点颜色为黑色
        while (x != root && colorOf(x) == BLACK) {
        		//如果x为左子结点
            if (x == leftOf(parentOf(x))) {
            		//定义sib为x的兄弟结点
                Entry<K,V> sib = rightOf(parentOf(x));
                //x的兄弟结点sib为红色:情况1.
                if (colorOf(sib) == RED) {
                		//将指定结点x的兄弟结点sib的颜色设置为黑色
                    setColor(sib, BLACK);
                    //将指定结点x的的父结点的颜色设置为红色
                    setColor(parentOf(x), RED);
                    //以指定结点x的父结点为中心,向左进行旋转
                    rotateLeft(parentOf(x));
                    //此时指定结点x的兄弟结点sib改变,重置兄弟结点
                    sib = rightOf(parentOf(x));
                }
                //兄弟结点sib的颜色为黑色,情况2、情况3、情况4
                //情况2:指定结点x的兄弟结点sib是黑色结点,而且sib的两个子结点都是黑色结点
                if (colorOf(leftOf(sib))  == BLACK &&
                    colorOf(rightOf(sib)) == BLACK) {
                    //将sib设置为红色结点
                    setColor(sib, RED);
                    //将x指向自己的父结点
                    x = parentOf(x);
                } else {
                		//情况3:指定结点x的兄弟结点sib是黑色结点,sib的右结点为黑色结点,左结点为红色结点
                		//将情况3转换为情况4
                    if (colorOf(rightOf(sib)) == BLACK) {
                    		//将sib的左结点设置为黑色结点
                        setColor(leftOf(sib), BLACK);
                        //将sib设置为红色
                        setColor(sib, RED);
                        //以sib为中心,向右进行旋转
                        rotateRight(sib);
                        //此时指定结点x的兄弟结点sib改变,重置兄弟结点
                        sib = rightOf(parentOf(x));
                    }
                    //情况4:指定结点x的兄弟结点sib为黑色结点,sib的右结点为红色结点
                    //将sib的结点颜色设置为x的父结点颜色
                    setColor(sib, colorOf(parentOf(x)));
                    //将x父结点的颜色设置为黑色
                    setColor(parentOf(x), BLACK);
                    //将sib的右结点的颜色设置为黑色
                    setColor(rightOf(sib), BLACK);
                    //以x的父结点为中心,向左尽心旋转
                    rotateLeft(parentOf(x));
                    x = root;
                }
            } else { 		//过程与之前一样,只是分为作为左右结点进行分析
                Entry<K,V> sib = leftOf(parentOf(x));

                if (colorOf(sib) == RED) {
                    setColor(sib, BLACK);
                    setColor(parentOf(x), RED);
                    rotateRight(parentOf(x));
                    sib = leftOf(parentOf(x));
                }

                if (colorOf(rightOf(sib)) == BLACK &&
                    colorOf(leftOf(sib)) == BLACK) {
                    setColor(sib, RED);
                    x = parentOf(x);
                } else {
                    if (colorOf(leftOf(sib)) == BLACK) {
                        setColor(rightOf(sib), BLACK);
                        setColor(sib, RED);
                        rotateLeft(sib);
                        sib = leftOf(parentOf(x));
                    }
                    setColor(sib, colorOf(parentOf(x)));
                    setColor(parentOf(x), BLACK);
                    setColor(leftOf(sib), BLACK);
                    rotateRight(parentOf(x));
                    x = root;
                }
            }
        }

        setColor(x, BLACK);
    }

三、TreeMap实现的部分方法

    //使用其键的自然排序构造一个新的、空的树形图。 插入map的所有key都必须实现Comparable。此外,
    //所有这些密钥必须相互比较k1.compareTo(k2)不得为任何k1和k2引发ClassCastException在map上。
    //如果用户试图将一个key放入违反该约束的地图map(例如,用户尝试将一个字符串键放入一个键为整数的map中),
    //put(Object key,Object value)调用将抛出ClassCastException。
    public TreeMap() {
        comparator = null;
    }

    //构造一个新的、空的树图,根据给定的比较器排序。 
    //插入到地图中的所有键必须由给定的比较器相互比较comparator.compare(k1,k2)
    //不得为任何k1和k2抛出ClassCastException。 
    //如果用户尝试将一个key放入违反此约束的map中,则put(Object key,Object value)调用将抛出ClassCastException
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

    //构造一个新的树图,其中包含与给定地图相同的映射,根据其key的自然排序进行排序。 
    //插入新地图的所有键必须实现Comparable接口。 此外,所有这些key必须相互比较k1.compareTo(k2)
    //不得在map上为k1和k2任何一个key引发ClassCastException。 此方法运行在n*log(n)时间。
    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }

    //构造一个包含相同映射并使用与指定排序映射相同顺序的新树映射。该方法运行在线性时间。
    public TreeMap(SortedMap<K, ? extends V> m) {
        comparator = m.comparator();
        try {
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }
    }

    // 查询操作

    //返回此映射中key-value映射的数量。
    public int size() {
        return size;
    }

    //如果此映射包含指定key的映射,则返回true
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }

    //如果此映射将一个或多个键映射到指定的值,则返回true。
    public boolean containsValue(Object value) {
        for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
            if (valEquals(value, e.value))
                return true;
        return false;
    }

    //返回指定key映射到的值,如果此映射不包含该key的映射,则返回null
    public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
    }

    public Comparator<? super K> comparator() {
        return comparator;
    }

    public K firstKey() {
        return key(getFirstEntry());
    }


    public K lastKey() {
        return key(getLastEntry());
    }

    //将指定map的所有映射复制到此map。
    public void putAll(Map<? extends K, ? extends V> map) {
        int mapSize = map.size();
        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
            // 如果TreeMap和map的比较器相等;则将map的元素全部拷贝到TreeMap中,然后返回
            Comparator<?> c = ((SortedMap<?,?>)map).comparator();
            if (c == comparator || (c != null && c.equals(comparator))) {
                ++modCount;
                try {
                    buildFromSorted(mapSize, map.entrySet().iterator(),
                                    null, null);
                } catch (java.io.IOException cannotHappen) {
                } catch (ClassNotFoundException cannotHappen) {
                }
                return;
            }
        }
        super.putAll(map);
    }

    //返回此映射的给定key的条目,如果映射不包含该key的条目,则返回null
    final Entry<K,V> getEntry(Object key) {
        // Offload comparator-based version for sake of performance
        if (comparator != null)
            return getEntryUsingComparator(key);
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = k.compareTo(p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
        return null;
    }

    //使用比较器的getEntry版本。从getEntry中分离来执行性能。 
    //(这对于大多数方法来说都不值得,因为比较器的性能不太依赖,但在这里是值得的。)
    final Entry<K,V> getEntryUsingComparator(Object key) {
        @SuppressWarnings("unchecked")
            K k = (K) key;
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            Entry<K,V> p = root;
            while (p != null) {
                int cmp = cpr.compare(k, p.key);
                if (cmp < 0)
                    p = p.left;
                else if (cmp > 0)
                    p = p.right;
                else
                    return p;
            }
        }
        return null;
    }

    //获取与指定key对应的条目; 
    //如果不存在这样的条目,则返回大于指定key的最小key的条目; 
    //如果不存在这样的条目(即,Tree中最大的key小于指定的key),返回 null
    final Entry<K,V> getCeilingEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp < 0) {
                if (p.left != null)
                    p = p.left;
                else
                    return p;
            } else if (cmp > 0) {
                if (p.right != null) {
                    p = p.right;
                } else {
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.right) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            } else
                return p;
        }
        return null;
    }

    //获取与指定key对应的条目; 
    //如果不存在这样的条目,则返回小于指定key的最大key的条目; 
    //如果没有这样的条目,返回null
    final Entry<K,V> getFloorEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp > 0) {
                if (p.right != null)
                    p = p.right;
                else
                    return p;
            } else if (cmp < 0) {
                if (p.left != null) {
                    p = p.left;
                } else {
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.left) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            } else
                return p;

        }
        return null;
    }

    //获取大于指定key的最小key的条目; 
    //如果不存在这样的条目,则返回大于指定key的最小key的条目; 
    //如果没有这样的条目返回null
    final Entry<K,V> getHigherEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp < 0) {
                if (p.left != null)
                    p = p.left;
                else
                    return p;
            } else {
                if (p.right != null) {
                    p = p.right;
                } else {
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.right) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            }
        }
        return null;
    }

    //返回小于指定key的最大key的条目; 
    //如果不存在这样的条目(即,树中的最小key大于指定的key),返回null
    final Entry<K,V> getLowerEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp > 0) {
                if (p.right != null)
                    p = p.right;
                else
                    return p;
            } else {
                if (p.left != null) {
                    p = p.left;
                } else {
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.left) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            }
        }
        return null;
    }

    //从此TreeMap中删除此key的映射(如果存在)。
    public V remove(Object key) {
        Entry<K,V> p = getEntry(key);
        if (p == null)
            return null;

        V oldValue = p.value;
        deleteEntry(p);
        return oldValue;
    }

    //从此map中删除所有的映射。此调用返回后,map将为空。
    public void clear() {
        modCount++;
        size = 0;
        root = null;
    }

    //返回此TreeMap实例的浅层副本。(key和value本身不被克隆。)
    public Object clone() {
        TreeMap<?,?> clone;
        try {
            clone = (TreeMap<?,?>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }

        // Put clone into "virgin" state (except for comparator)
        clone.root = null;
        clone.size = 0;
        clone.modCount = 0;
        clone.entrySet = null;
        clone.navigableKeySet = null;
        clone.descendingMap = null;

        // Initialize clone with our mappings
        try {
            clone.buildFromSorted(size, entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }

        return clone;
    }

    // NavigableMap API methods

    //返回与此映射中的最小键相关联的键值映射,如果映射为空,则返回null。
    public Map.Entry<K,V> firstEntry() {
        return exportEntry(getFirstEntry());
    }

    //返回与该地图中最大关键字关联的键值映射,如果地图为空,则返回null。
    public Map.Entry<K,V> lastEntry() {
        return exportEntry(getLastEntry());
    }

    //删除并返回与该映射中的最小密钥相关联的键值映射,如果映射为空,则返回null。
    public Map.Entry<K,V> pollFirstEntry() {
        Entry<K,V> p = getFirstEntry();
        Map.Entry<K,V> result = exportEntry(p);
        if (p != null)
            deleteEntry(p);
        return result;
    }

    //删除并返回与该地图中最大键相关联的键值映射,如果地图为空,则返回null。
    public Map.Entry<K,V> pollLastEntry() {
        Entry<K,V> p = getLastEntry();
        Map.Entry<K,V> result = exportEntry(p);
        if (p != null)
            deleteEntry(p);
        return result;
    }

    //返回与最大密钥相关联的密钥值映射严格小于给定密钥,如果没有这样的密钥,则返回null。
    public Map.Entry<K,V> lowerEntry(K key) {
        return exportEntry(getLowerEntry(key));
    }

    //返回严格小于给定键的最大键,如果没有这样的键返回null。
    public K lowerKey(K key) {
        return keyOrNull(getLowerEntry(key));
    }

    //返回与小于或等于给定键的最大键相关联的键值映射,如果没有此键,则返回null。
    public Map.Entry<K,V> floorEntry(K key) {
        return exportEntry(getFloorEntry(key));
    }

    //返回小于或等于给定键的最大键,如果没有此键,则返回null。
    public K floorKey(K key) {
        return keyOrNull(getFloorEntry(key));
    }

    //返回与最小键相关联的键值映射大于或等于给定键,如果没有此键,则返回null。
    public Map.Entry<K,V> ceilingEntry(K key) {
        return exportEntry(getCeilingEntry(key));
    }

    //返回大于或等于给定键的最小键,如果没有此键,则返回null。
    public K ceilingKey(K key) {
        return keyOrNull(getCeilingEntry(key));
    }

    //返回与最小键相关联的键值映射严格大于给定的键,如果没有这样的键,则返回null。
    public Map.Entry<K,V> higherEntry(K key) {
        return exportEntry(getHigherEntry(key));
    }

    //Returns the least key strictly greater than the given key, or null if there is no such key.
    public K higherKey(K key) {
        return keyOrNull(getHigherEntry(key));
    }
  
 
    //返回此映射中包含的映射的反向排序视图。
    public NavigableMap<K, V> descendingMap() {
        NavigableMap<K, V> km = descendingMap;
        return (km != null) ? km :
            (descendingMap = new DescendingSubMap<>(this,
                                                    true, null, true,
                                                    true, null, true));
    }

    //返回该地图的部分的视图,其关键范围从fromKey到kyo。
    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
                                    K toKey,   boolean toInclusive) {
        return new AscendingSubMap<>(this,
                                     false, fromKey, fromInclusive,
                                     false, toKey,   toInclusive);
    }

    //返回该地图的部分的视图,其键值小于(或等于,如果包含值为true)toKey。
    public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
        return new AscendingSubMap<>(this,
                                     true,  null,  true,
                                     false, toKey, inclusive);
    }

    //返回这个地图的部分的视图,其键大于(或等于,如果包含值为true)fromKey。
    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
        return new AscendingSubMap<>(this,
                                     false, fromKey, inclusive,
                                     true,  null,    true);
    }

    //返回该地图部分的视图,其关键范围从fromKey(包括)到toKey(独占)。
    public SortedMap<K,V> subMap(K fromKey, K toKey) {
        return subMap(fromKey, true, toKey, false);
    }

    //返回该地图的部分密钥严格小于toKey的视图。
    public SortedMap<K,V> headMap(K toKey) {
        return headMap(toKey, false);
    }

    //返回此地图部分的视图,其键大于或等于fromKey。
    public SortedMap<K,V> tailMap(K fromKey) {
        return tailMap(fromKey, true);
    }

    //仅当当前映射到指定的值时,才能替换指定键的条目。
    public boolean replace(K key, V oldValue, V newValue) {
        Entry<K,V> p = getEntry(key);
        if (p!=null && Objects.equals(oldValue, p.value)) {
            p.value = newValue;
            return true;
        }
        return false;
    }

    //只有当目标映射到某个值时,才能替换指定键的条目。
    public V replace(K key, V value) {
        Entry<K,V> p = getEntry(key);
        if (p!=null) {
            V oldValue = p.value;
            p.value = value;
            return oldValue;
        }
        return null;
    }

    //对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
    public void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        int expectedModCount = modCount;
        for (Entry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
            action.accept(e.key, e.value);

            if (expectedModCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }
    }

    //将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。
    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        int expectedModCount = modCount;

        for (Entry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
            e.value = function.apply(e.key, e.value);

            if (expectedModCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }
    }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值