从源码理解TreeMap.java

本文将详细探讨Java中TreeMap的数据结构和工作原理,通过分析源码揭示其内部节点组织、插入、删除、查找等操作的具体过程,帮助读者深入理解这个有序的键值对集合。
摘要由CSDN通过智能技术生成

从源码理解TreeMap.java

package java.util;

import java.io.Serializable;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * 基于红黑树的NavigableMap接口实现
 * Map是根据关键字的自然比较序排序,或是根据创建时初始化的比较器的比较结果排序
 * 这个实现保证提供log(n)时间的操作:containsKey、get、put、remove
 * 树形Map的顺序是保持不变的,和其他有序Map一样,不管有没有提供显式的比较器,而且必须和equals兼容
 *  注意,这个实现是不支持并发访问的。需要外部显式同步,如下:
 *	SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));
 * 所有集合视图返回的迭代器都是快速失败的(fail-fast)
 */

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
    /**
     * 用于保持顺序的比较器,如果为空,使用自然序保持Key的顺序
     */
    private final Comparator<? super K> comparator;
    //根节点
    private transient Entry<K,V> root = null;

    /**
     * 树中的结点数量
     */
    private transient int size = 0;

    /**
     * 用于记录结构上的改变次数
     */
    private transient int modCount = 0;

    /**
     * 构造方法一,默认构造方法,Comparator为空,即采用自然序维持TreeMap中结点的顺序
     */
    public TreeMap() {
        comparator = null;
    }

    /**
     * 构造方法二,提供指定的比较器,如果为空,还是自然序
     */
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

    /**
     * 构造方法三,采用自然序维持TreeMap中结点的顺序,同时将传入的Map中的内容添加到TreeMap中
     */
    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }

    /**
     * 构造方法四,接受SortedMap参数,根据SortedMap的比较器维持TreeMap中的结点顺序,
     * 同时通过buildFromSorted(int size, Iterator it, 
     * java.io.ObjectInputStream str, V defaultVal)方法将SortedMap中的 内容添加到TreeMap中
     */
    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) {
        }
    }

    // 查询操作
    /**
     * 返回Map中键值对数目
     */
    public int size() {
        return size;
    }

    /**
     * 是否包含指定关键字
     */
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }

    /**
     * 是否包含指定值,时间复杂度和Map大小成正比
     */
    public boolean containsValue(Object value) {
    			//通过e = successor(e)实现对树的遍历
        for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
        		//判断结点值是否和value相等
            if (valEquals(value, e.value))
                return true;       
        		//若没有,返回false
        return false;
    }

    /**
     * 返回指定关键字的值,没有则返回null
     * 返回null不代表不存在,也有可能是值就是null
     * @throws ClassCastException if the specified key cannot be compared
     *         with the keys currently in the map
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     */
    public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
    }

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

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public K firstKey() {
        return key(getFirstEntry());
    }

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public K lastKey() {
        return key(getLastEntry());
    }

    /**
     * 将指定Map中的映射复制进来,会取代当前已存在的映射值
     * @param  map mappings to be stored in this map
     * @throws ClassCastException if the class of a key or value in
     *         the specified map prevents it from being stored in this map
     * @throws NullPointerException if the specified map is null or
     *         the specified map contains a null key and this map does not
     *         permit null keys
     */
    public void putAll(Map<? extends K, ? extends V> map) {
        int mapSize = map.size();
        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
            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获取对应的结点
     * @return this map's entry for the given key, or {@code null} if the map
     *         does not contain an entry for the key
     * @throws ClassCastException if the specified key cannot be compared
     *         with the keys currently in the map
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     */
    final Entry<K,V> getEntry(Object key) {
        	// 如果有比较器,返回getEntryUsingComparator(Object key)的结果
        if (comparator != null)
            return getEntryUsingComparator(key);
        	//查找的Key为null,抛出NullPointerException
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
        	//如果没有比较器,而是实现了 可比较接口
            Comparable<? super K> k = (Comparable<? super K>) key;
        	//获取根节点
        Entry<K,V> p = root;
        	//对树进行遍历查找结点
        while (p != null) {
        		//把Key和当前节点的Key进行比较
            int cmp = k.compareTo(p.key);
            	//Key小于当前结点的Key
            if (cmp < 0)
            		//p“移动”到左节点上
                p = p.left;
            	//key大于当前节点的Key
            else if (cmp > 0)
            		//p移动到右结点上
                p = p.right;
            	//key值相等则当前节点就是要找的结点
            else
            		//返回找到的结点
                return p;
        }
        	//没有找到则返回null
        return null;
    }

    /**
     * 有比较器时获取指定关键字的Entry的方法
     */
    final Entry<K,V> getEntryUsingComparator(Object key) {
        @SuppressWarnings("unchecked")
            K k = (K) key;
        	//获取比较器
        Comparator<? super K> cpr = comparator;
        	//其实在调用此方法的get(Object key)中已经对比较器为null的情况进行判断,这里是防御性的判断
        if (cpr != null) {
        		//获取根节点
            Entry<K,V> p = root;
            	//遍历树
            while (p != null) {
            		//获取Key和当前节点的Key的比较结果
                int cmp = cpr.compare(k, p.key);
                	//查找的Key值较小
                if (cmp < 0)
                		//p移动到左孩子
                    p = p.left;
                	//查找的Key值较大
                else if (cmp > 0)
                		//p移动到右结点
                    p = p.right;
                	//key值相等
                else
                		//返回找到的结点
                    return p;
            }
        }
        	//没找到Key值对应的结点,返回null
        return null;
    }

    /**
     * 获取指定关键字对应的Entry,如果没有就返回大于该关键字的最小关键字的Entry
     * 如没有,返回null
     */
    final Entry<K,V> getCeilingEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            			//key比较小
            if (cmp < 0) {
            			//进入左子树遍历
                if (p.left != null)
                    p = p.left;
                else
                    return p;
            } else if (cmp > 0) {		//key比较大
            			//进入右子树遍历
                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;
    }

    /**
     * 获取指定关键字对应的Entry,如果没有对应的Entry,返回小于等于指定关键字的最大关键字的Entry,
     * 如果不存在,返回null
     */
    final Entry<K,V> getFloorEntry(K key) {
    			//获取根节点
        Entry<K,V> p = root;
        		//不是空树,对树进行遍历
        while (p != null) {
            int cmp = compare(key, p.key);
            		//key较大
            if (cmp > 0) {
            			//找到结点有右孩子,则继续向右孩子遍历
                if (p.right != null)
                    p = p.right;
                else		//没有右孩子,那么p结点就是树中比传入key值小且最接近传入key的结点,就是要找的结点
                    return p;
            } else if (cmp < 0) {	//key值较小
            				//由左孩子向左孩子遍历
                if (p.left != null) { 		
                    p = p.left;
                } else {	//没有左孩子,这个结点比key值大,
                			//返回内容是向上寻找到的根节点或比传入key值小的最后一个结点
                    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	//Key值相等
                return p;

        }
        return null;
    }

    /**
     * 获取指定关键字对应的Entry,如果没有对应的Entry,返回严格大于指定关键字的最小关键字的Entry,
     * 如果没有则返回null
     */
    final Entry<K,V> getHigherEntry(K key) {
    				//获取根节点
        Entry<K,V> p = root;
        			//树不空,遍历树
        while (p != null) {
            int cmp = compare(key, p.key);
            			//key比较小
            if (cmp < 0) {
            			//有左孩子,去左子树遍历
                if (p.left != null)
                    p = p.left;
                else	//没有左孩子,那么p结点就是树中比传入key值大且最接近传入key的结点了
                    return p;
            } else { 	//key比较大
            			//有右子树,向右子树遍历
                if (p.right != null) {
                    p = p.right;
                } else {	//没有右孩子,这个结点比key小,
                			//返回内容是向上寻找到根节点或是比传入key值大的最后一个结点
                    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;
    }

    /**
     * 返回严格小于指定关键字的的最大关键字的Entry
     */
    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;
    }

    /**将指定关键字和指定值联系起来,如已存在,覆盖
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     *
     * @return the previous value associated with {@code key}, or
     *         {@code null} if there was no mapping for {@code key}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code key}.)
     * @throws ClassCastException if the specified key cannot be compared
     *         with the keys currently in the map
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     */
    public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); 	// 类型检查(可能为null)
            					//如果根节点为null,将传入的键值对构造成根节点(根节点没有父节点,所以传入的父节点为null)
            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 while实现从根节点root开始移动寻找传入键值对需要插入的位置
            do {
            				//记录将要被插入新的键值对的上一个结点(即新节点的父节点)
                parent = t;
                			//使用比较器比较父节点和插入键值对的Key值的大小
                cmp = cpr.compare(key, t.key);
                			//插入的Key较大,进入左子树
                if (cmp < 0)
                    t = t.left;
                			//插入的Key较小,进入右子树
                else if (cmp > 0)
                    t = t.right;
                			//key值相等,替换并返回t结点的value(put方法结束)
                else
                    return t.setValue(value);
            } while (t != null);
        }
        				//没有比较器的处理
        else {
        				//Key为null,抛出NullPointerException异常
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            			//与if中的do while类似,只是比较的方式不同
            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
        size++;
        modCount++;
        		//因为是插入新节点,所以返回是null
        return null;
    }

    /**
     * 删除指定关键字的映射
     * @param  key key for which mapping should be removed
     * @return the previous value associated with {@code key}, or
     *         {@code null} if there was no mapping for {@code key}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code key}.)
     * @throws ClassCastException if the specified key cannot be compared
     *         with the keys currently in the map
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     */
    public V remove(Object key) {
    		//通过getEntry(Object key)获取结点
        Entry<K,V> p = getEntry(key);
        	//指定Key的结点不存在,返回null
        if (p == null)
            return null;
        	//获取结点的value
        V oldValue = p.value;
        	//删除结点
        deleteEntry(p);
        	//返回结点的值
        return oldValue;
    }

    /**
     * 清空Map
     */
    public void clear() {
        modCount++;
        size = 0;
        root = null;
    }

    /**
     * Returns a shallow copy of this {@code TreeMap} instance. (The keys and
     * values themselves are not cloned.)
     *
     * @return a shallow copy of this map
     */
    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接口的函数

    /**
     * @since 1.6
     */
    public Map.Entry<K,V> firstEntry() {
        return exportEntry(getFirstEntry());
    }

    /**
     * @since 1.6
     */
    public Map.Entry<K,V> lastEntry() {
        return exportEntry(getLastEntry());
    }

    /**
     * 获取并移除最小结点
     * @since 1.6
     */
    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;
    }

    /**
     * 获取并移除最大结点
     * @since 1.6
     */
    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;
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public Map.Entry<K,V> lowerEntry(K key) {
        return exportEntry(getLowerEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public K lowerKey(K key) {
        return keyOrNull(getLowerEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public Map.Entry<K,V> floorEntry(K key) {
        return exportEntry(getFloorEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public K floorKey(K key) {
        return keyOrNull(getFloorEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public Map.Entry<K,V> ceilingEntry(K key) {
        return exportEntry(getCeilingEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public K ceilingKey(K key) {
        return keyOrNull(getCeilingEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public Map.Entry<K,V> higherEntry(K key) {
        return exportEntry(getHigherEntry(key));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified key is null
     *         and this map uses natural ordering, or its comparator
     *         does not permit null keys
     * @since 1.6
     */
    public K higherKey(K key) {
        return keyOrNull(getHigherEntry(key));
    }

    // Views
    /**
     * Fields initialized to contain an instance of the entry set view
     * the first time this view is requested.  Views are stateless, so
     * there's no reason to create more than one.
     */
    private transient EntrySet entrySet = null;
    private transient KeySet<K> navigableKeySet = null;
    private transient NavigableMap<K,V> descendingMap = null;

    /**
     * Returns a {@link Set} view of the keys contained in this map.
     *
     * <p>The set's iterator returns the keys in ascending order.
     * The set's spliterator is
     * <em><a href="Spliterator.html#binding">late-binding</a></em>,
     * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED}
     * and {@link Spliterator#ORDERED} with an encounter order that is ascending
     * key order.  The spliterator's comparator (see
     * {@link java.util.Spliterator#getComparator()}) is {@code null} if
     * the tree map's comparator (see {@link #comparator()}) is {@code null}.
     * Otherwise, the spliterator's comparator is the same as or imposes the
     * same total ordering as the tree map's comparator.
     *
     * <p>The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own {@code remove} operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * {@code Iterator.remove}, {@code Set.remove},
     * {@code removeAll}, {@code retainAll}, and {@code clear}
     * operations.  It does not support the {@code add} or {@code addAll}
     * operations.
     */
    public Set<K> keySet() {
        return navigableKeySet();
    }

    public NavigableSet<
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值