Java集合源码分析(七)——TreeMap

简介

TreeMap 是一个有序的key-value集合,它的内部是通过红黑树实现的。
TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。
TreeMap 实现了NavigableMap接口,说明它支持一系列的导航方法。比如返回有序的key集合。
TreeMap 实现了Cloneable接口,说明它能被克隆。
TreeMap 实现了java.io.Serializable接口,说明它支持序列化。

TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。

源码分析

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable{}

字段

	// 比较器,决定排序
    private final Comparator<? super K> comparator;
	// 红黑树根节点 
    private transient Entry<K,V> root;
	// 红黑树节点数量
    private transient int size = 0;
	// 修改次数
    private transient int modCount = 0;

构造函数

	// 默认构造
    public TreeMap() {
        comparator = null;
    }
	// 传入比较器
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
	// 传入原表
    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) {
        }
    }

内部类

1.树节点结构

	// 红黑树节点
    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;

        // 节点构造器
        Entry(K key, V value, Entry<K,V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
        }

        // 获取键
        public K getKey() {
            return key;
        }

        // 获取值
        public V getValue() {
            return 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;
        }
    }

2.迭代器

	// 当前类私有迭代器,实现了迭代器的接口
    abstract class PrivateEntryIterator<T> implements Iterator<T> {
    	// 下一个节点
        Entry<K,V> next;
        // 最后依次返回的节点
        Entry<K,V> lastReturned;
        // 用于实现fast-tail
        int expectedModCount;

        PrivateEntryIterator(Entry<K,V> first) {
            expectedModCount = modCount;
            lastReturned = null;
            next = first;
        }
		// 是否存在下一个节点
        public final boolean hasNext() {
            return next != null;
        }
		// 返回下一个键值对
        final Entry<K,V> nextEntry() {
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            // 将next再指向下一个节点
            next = successor(e);
            // 更新最近返回的节点
            lastReturned = e;
            return e;
        }
		// 返回前一个键值对
        final Entry<K,V> prevEntry() {
            Entry<K,V> e = next;
            // 下一个节点不为空
            if (e == null)
                throw new NoSuchElementException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            // 将next指向返回节点的前一个节点
            next = predecessor(e);
            // 更新最近返回的节点
            lastReturned = e;
            return e;
        }
		// 删除当前节点
        public void remove() {
            if (lastReturned == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            // deleted entries are replaced by their successors
            if (lastReturned.left != null && lastReturned.right != null)
                next = lastReturned;
            // 调用了内部函数删除
            deleteEntry(lastReturned);
            expectedModCount = modCount;
            lastReturned = null;
        }
    }
    
	// 键值的迭代器
    final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> {
    	// 获取父类抽象类的迭代器
        EntryIterator(Entry<K,V> first) {
            super(first);
        }
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }
	

3.集合

// 获取键值集合
    class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    	// 返回迭代器,并送入头节点
        public Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator(getFirstEntry());
        }
		// 是否包含该节点
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
            Object value = entry.getValue();
            Entry<K,V> p = getEntry(entry.getKey());
            return p != null && valEquals(p.getValue(), value);
        }
		// 删除当前节点
        public boolean remove(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
            Object value = entry.getValue();
            Entry<K,V> p = getEntry(entry.getKey());
            if (p != null && valEquals(p.getValue(), value)) {
                deleteEntry(p);
                return true;
            }
            return false;
        }

        public int size() {
            return TreeMap.this.size();
        }

        public void clear() {
            TreeMap.this.clear();
        }

        public Spliterator<Map.Entry<K,V>> spliterator() {
            return new EntrySpliterator<K,V>(TreeMap.this, null, null, 0, -1, 0);
        }
    }

方法

1.元素添加

	// 添加新的键值对
    public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check
			// 如果根节点是空的,则指定根节点
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        // 保存最新的比较结果
        int cmp;
        Entry<K,V> parent;
        // 获取比较器的引用
        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 {
        	// 如果没有指定比较器,那么直接用调用Key的compareTo接口
            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);
        }
        // 没有找到相同的Key,那就构建当新节点再插到红黑树中
        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.元素获取

	// 根据Key值获取元素
    public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
    }
	// 根据key值获取entry节点
    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")
        	// 利用key对象的比较接口
            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;
    }

	// 利用传入的比较器进行查询
    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;
    }

3.元素删除

	// 删除指定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;
    }

	// 红黑树中删除对应节点
    private void deleteEntry(Entry<K,V> p) {
        modCount++;
        size--;

        // If strictly internal, copy successor's element to p and then make p
        // point to successor.
        if (p.left != null && p.right != null) {
        	// 返回p节点的后继节点
            Entry<K,V> s = successor(p);
            p.key = s.key;
            p.value = s.value;
            p = s;
        } // p has 2 children

        // Start fixup at replacement node, if it exists.
        Entry<K,V> replacement = (p.left != null ? p.left : p.right);

        if (replacement != null) {
            // Link replacement to parent
            replacement.parent = p.parent;
            if (p.parent == null)
                root = replacement;
            else if (p == p.parent.left)
                p.parent.left  = replacement;
            else
                p.parent.right = replacement;

            // Null out links so they are OK to use by fixAfterDeletion.
            p.left = p.right = p.parent = null;

            // Fix replacement
            if (p.color == BLACK)
                fixAfterDeletion(replacement);
        } else if (p.parent == null) { // return if we are the only node.
            root = null;
        } else { //  No children. Use self as phantom replacement and unlink.
            if (p.color == BLACK)
                fixAfterDeletion(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;
            }
        }
    }

4.克隆

    public Object clone() {
        TreeMap<?,?> clone;
        try {
            clone = (TreeMap<?,?>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }

        // 初始化参数
        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;
    }

5.序列化

	// 将TreeMap转化为输出流
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // Write out the Comparator and any hidden stuff
        s.defaultWriteObject();

        // Write out size (number of Mappings)
        s.writeInt(size);

        // 通过有序的遍历依次写入键值对
        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<K,V> e = i.next();
            s.writeObject(e.getKey());
            s.writeObject(e.getValue());
        }
    }

	// 将输入流转化为TreeMap
    private void readObject(final java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in the Comparator and any hidden stuff
        s.defaultReadObject();

        // Read in size
        int size = s.readInt();

        buildFromSorted(size, null, s, null);
    }
	// 从有序的流中建立TreeMap
    private void buildFromSorted(int size, Iterator<?> it,
                                 java.io.ObjectInputStream str,
                                 V defaultVal)
        throws  java.io.IOException, ClassNotFoundException {
        this.size = size;
        root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
                               it, str, defaultVal);
    }

红黑树相关

总结

TreeMap本质上就是一棵红黑树。
该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。

posted @ 2020-12-07 19:52  lippon  阅读(116)  评论(0编辑  收藏  举报