Osheep

时光不回头,当下最重要。

源码的魅力 - TreeMap 的工作原理

源码的魅力 – TreeMap 的工作原理(Android 7.1源码)

简介

由于HashMap与linkedHashMap都不能按照key的数据顺序进行遍历,所以后来就有了TreeMap。

怎么做到按照插入顺序排序的呢

    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

    public V put(K key, V value) {
        TreeMapEntry<K,V> t = root;
        if (t == null) {
            if (comparator != null) {
                if (key == null) {
                    comparator.compare(key, key);
                }
            } else {
                if (key == null) {
                    throw new NullPointerException("key == null");
                } else if (!(key instanceof Comparable)) {
                    throw new ClassCastException(
                            "Cannot cast" + key.getClass().getName() + " to Comparable.");
                }
            }

            root = new TreeMapEntry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        TreeMapEntry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            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);
        }
        TreeMapEntry<K,V> e = new TreeMapEntry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

TreeMap存在一个参数为Comparator的构造函数,在插入数据时默认是使用数据的默认比较器,否则使用比较器,通过比较器比较的值,如果相等则直接替换,如果不同则插入,使用红黑树维护整个结构。

怎么获取数据时是有序的呢

    abstract class PrivateEntryIterator<T> implements Iterator<T> {
        TreeMapEntry<K,V> next;
        TreeMapEntry<K,V> lastReturned;
        ...

        final TreeMapEntry<K,V> nextEntry() {
            TreeMapEntry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            next = successor(e);
            lastReturned = e;
            return e;
        }
    }

    //中序遍历查找下一个节点
    static <K,V> TreeMapEntry<K,V> successor(TreeMapEntry<K,V> t) {
        if (t == null)
            return null;
        else if (t.right != null) {
            TreeMapEntry<K,V> p = t.right;
            while (p.left != null)
                p = p.left;
            return p;
        } else {
            TreeMapEntry<K,V> p = t.parent;
            TreeMapEntry<K,V> ch = t;
            while (p != null && ch == p.right) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

通过PrivateEntryIterator遍历器然后,通过中序遍历返回数据,正是排序的数据。

点赞