[Java Collections Framework] 浅析java 集合框架(六) : TreeMap

特性

  1. 底层是红黑树,算法基于经典书籍 《Introduction to Algorithm》
  2. key 需要实现comparable 接口,或者提供comparator
  3. Views:
    - EntrySet: Set OF Map.Enty OF Key-Value
    - Value : Collection Of Value
    - KeySet : Set
  4. 所有的遍历基于上面提供的三种视图,返回的所有pair OF key-value 支持 pair.setValue
  5. 提供了基于sortedMap的三种子视图:
    - subMap: from,to
    - headMap
    - tailMap
  6. O ( l o g N ) 的增删改查, 以及

Methods {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry}, and {@code higherEntry} return {@code Map.Entry} objects associated with keys respectively less than, less than or equal,greater than or equal, and greater than a given key, returning {@code null} if there is no such key

后面是一些源码上的收获

higherEntry,ceilingEntry

这两个的区别一个是严格大,另外一个是大于等于,在代码上仅体现在一行。

    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;// p > key
            } 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;
    }

看那个else

    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;
    }

迭代器的时间复杂度

值得说的是迭代器的方法 next 的时间复杂度并不是 O(1) 的,因为他没有像HashMap中的树箱一样,提供next索引到下一个,而是通过一个Successer或者pre方法求的下一个,所以这里的复杂度是当前迭代器的树高。不过值得庆幸的是由于红黑树的高度平衡的特性,遍历完整棵树的复杂度还是 O ( n ) 的,不过常数比较高,(这里我口胡了一下,并没有证明,我是想到了由堆的直接创建方法计算中的复杂度是 O ( n ) ,这里红黑树的高度平衡性,完全可以同过补节点的方法,让他是完全二叉的,)。

        final Entry<K,V> nextEntry() {
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            next = successor(e);//访问e的后继
            lastReturned = e;
            return e;
        }

疑问

comparable和comparator两种比较方式,源代码中大量用到了,两种不同的比较方式,我认为完全可以在key是comparable而没有提供comparator的时候,将其封装出一个comparator从而让后续代码都基于一种比较方式,做更简单的设计,不知作者这样做到底能带来多大的时间上的优化。

比如get方法中的

    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;
    }

猜你喜欢

转载自blog.csdn.net/Dylan_Frank/article/details/81286234