美文网首页
Java集合·08·TreeMap详解

Java集合·08·TreeMap详解

作者: Lynn_R01612x2 | 来源:发表于2018-03-26 23:42 被阅读0次

    一、概述

    TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。

    TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。

    TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。

    TreeMap 实现了Cloneable接口,意味着它能被克隆。

    TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。

    SortedMap

    扩展自Map接口,定义了有序的key-value键值对映射集合。根据key排序,使用Comparable或者Comparator进行排序。

    特点:

    • key需要支持排序。

    submap:

    • 1half-open they include their low* endpoint but not their high endpoint (where applicable)
    • 1closed range which includes both endpoints
    • 1open range which contains neither endpoint

    定义API:

    比较器相关:

    • comparator():Comparator

    视图相关:

    • subMap(K, K): SortedMap<K, V>
    • headMap(K): SortedMap<K, V>
    • tailMap(K): SortedMap<K, V>

    定位相关:

    • firstKey(): K
    • lastKey(): K

    NavigableMap

    扩展自SortedMap接口,添加搜索相关API,支持顺序遍历和反序遍历

    定位相关API(Entry/key):

    • lowerEntry(K): Entry<K, V>
    • floorEntry(K): Entry<K, V>
    • ceilingEntry(K): Entry<K, V>
    • higherEntry(K): Entry<K, V>
    • firstEntry(): Entry<K, V>
    • lastEntry(): Entry<K, V>

    action:

    • pollFirstEntry(): Entry<K, V>
    • pollLastEntry(): Entry<K, V>

    反序列表:

    • descendingMap():NavigableMap<K, V>
    • descendingKeySet():NavigableSet<K>

    视图相关:

    • navigableKeySet(): NavigableSet<K>
    • subMap(K, K):NavigableMap<K, V>
    • headMap(K): NavigableMap<K, V>
    • tailMap(K): NavigableMap<K, V>

    注意点:

    NavigableMap中视图相关方法与SortedMap中视图相关方法不同,NavigableMap中返回类型为NavigableMap,SortedMap中返回类型为SortedMap

    二、数据结构

    TreeMap是通过红黑树实现的,TreeMap存储的是key-value键值对,TreeMap的排序是基于对key的排序。

    使用链式结构存储元素,只记录root节点。使用size保存元素数量。

    private transient TreeMapEntry<K,V> root = null;
    private transient int size = 0;
    

    保存一个Comparator,同于key排序。

    private final Comparator<? super K> comparator;
    

    TreeMapEntry

    实现了Map.Entry<K,V>接口,保存基本key、value信息。

    持有父节点、左子节点、右子节点的引用。

    记录本节点的颜色(红黑树需要)。

    K key;
    V value;
    TreeMapEntry<K,V> left = null;
    TreeMapEntry<K,V> right = null;
    TreeMapEntry<K,V> parent;
    boolean color = BLACK;
    

    红黑树(R-B Tree)

    R-B Tree,全称是Red-Black Tree,又称为“红黑树”。

    基本操作

    • 左旋
    • 右旋
    • 插入
    • 插入修正
    • 删除
    • 删除修正

    时间复杂度:基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n)

    三、特点

    • 有序,可使用Comparator进行排序,或者对key进行默认排序。
    • Iterator是fail-fast的
    • 非线程安全。可使用Collections.synchronizedSortedMap()
    • 性能稳定。基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n)
    • 对外Entry为snapshots,不可修改。
    • 不支持key为null值,value可以为null。

    四、实现原理

    1.基本方法

    构造函数

    四个:空构造函数、Comparator构造函数、Map构造函数、SortedMap构造函数

    SortedMap构造函数:获取SortedMap的Comparator,设置为自身的Comparator

        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不能为null,value不能为null,插入到红黑树中

    删除 - getEntry(key),然后删除该节点

    clear - 设置root为null,size为null

    查询(见下面具体分类)

    entry相关操作

    查询:

    getEntry:根据红黑树性质查找节点

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

    firstEntry: 返回最left的节点

        final TreeMapEntry<K,V> getFirstEntry() {
            TreeMapEntry<K,V> p = root;
            if (p != null)
                while (p.left != null)
                    p = p.left;
            return p;
        }
    

    lastEntry: 返回最right的节点

        final TreeMapEntry<K,V> getLastEntry() {
            TreeMapEntry<K,V> p = root;
            if (p != null)
                while (p.right != null)
                    p = p.right;
            return p;
        }
    

    注意:

    返回的entry并不是真实的元素,是新生的一个不可修改的entry,避免通过entry修改map结构

        static <K,V> Map.Entry<K,V> exportEntry(TreeMapEntry<K,V> e) {
            return (e == null) ? null :
                new AbstractMap.SimpleImmutableEntry<>(e);
        }
    

    key相关操作

    containsKey:使用Comparator比较key

        final TreeMapEntry<K,V> getEntryUsingComparator(Object key) {
            @SuppressWarnings("unchecked")
                K k = (K) key;
            Comparator<? super K> cpr = comparator;
            if (cpr != null) {
                TreeMapEntry<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;
        }
    

    value相关操作

    containValue :使用了两个内部方法 successor(TreeMapEntry<K,V> t)和predecessor(TreeMapEntry<K,V> t),用于返回仅大于/小于当前entry的key的entry,通过这两个方法遍历map即根据key的顺序来便利map。

       public boolean containsValue(Object value) {
            for (TreeMapEntry<K,V> e = getFirstEntry(); e != null; e = successor(e))
                if (valEquals(value, e.value))
                    return true;
            return false;
        }
    

    2.访问方式

    PrivateEntryIterator

    实现Iterator类,持有next和lastReturned两个指针。

            TreeMapEntry<K,V> next;
            TreeMapEntry<K,V> lastReturned;
            int expectedModCount;
    

    支持前/后移动和查询、删除操作。

    调用主类中的successor(e)和 predecessor(e)方法获取下一个/上一个entry。

    EntryIterator

    继承PrivateEntryIterator

    next返回entry

    KeyIterator

    继承PrivateEntryIterator

    next返回key

    ValueIterator

    继承PrivateEntryIterator

    next返回value

    DescendingKeyIterator

    继承PrivateEntryIterator

    next返回prevEntry

    重写remove方法,删除前一个元素。

    3.排序原理

    默认排序,Comparable natural ordering of keys

    Comparator排序

    五、视图

    支持四种视图,EntrySet、KeySet、Values和SubMap,SubMap又可分为顺序和逆序两种。

    NavigableSubMap

    继承AbstractMap,持有原NavigableMap的引用。记录lowKey、highKey或者直到Start、End,以及边缘值的包含关系。

            final TreeMap<K,V> m;
            final K lo, hi;
            final boolean fromStart, toEnd;
            final boolean loInclusive, hiInclusive;
    

    API

    • 支持大部分NavigableMap方法,通过调用原map实现。
    • 支持继续生成subMap。(Abstract)方法。
    • 包含自己的entrySet、keySet、values
    • 包含自己的Iterator

    子类AscendingSubMap和DescendingSubMap,分别表示顺序和逆序。

    EntrySet

    继承AbstractSet<Map.Entr<K,V>>

    调用原Map方法实现,Iterator返回EntryIterator

    KeySet

    继承AbstractSet<Map.Entr<K,V>>,实现NavigableSet<E>接口。

    调用原Map方法实现,Iterator返回KeyIterator/DescendingKeyIterator

    Values

    继承AbstractCollection<V>

    调用原Map方法实现

    六、性能

    时间复杂度:基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n)

    证明过程略。

    相关文章

      网友评论

          本文标题:Java集合·08·TreeMap详解

          本文链接:https://www.haomeiwen.com/subject/uiwdcftx.html