Java语言之TreeMap源码分析(jdk1.8)

1、TreeMap特点及其使用

        TreeMap的底层实现是一颗红黑树,学过数据结构的我们都知道红黑树也是平衡二叉树的一种,其最大的特点在与有序,其父节点左边的所有节点的值都是小于父节点的值,父节点右边所有节点的值都是大于父节点的值。故中序遍历以后得到的序列肯定是一个有序序列。TreeMap基于此数据结构故也是有序的


2、TreeMap数据结构

     2、1存储

        TreeMap的存储以及TreeMap中节点的储存
    //比较器
    private final Comparator<? super K> comparator;

    //红黑树的根节点
    private transient Entry<K,V> root;

    /**
     * The number of entries in the tree
     */
	//树中节点的个数
    private transient int size = 0;

    /**
     * The number of structural modifications to the tree.
     */
    private transient int modCount = 0;
	
	
	//红黑树中节点的存储结构
	 static final class Entry<K,V> implements Map.Entry<K,V> {
		 
		//本身所存储的key-value值
        K key;
        V value;
		
		//左孩子的引用
        Entry<K,V> left;
		
		//右孩子的引用
        Entry<K,V> right;
		
		//指向其父节点
        Entry<K,V> parent;
		
		//指定红黑树的颜色属性
        boolean color = BLACK;
	 }

     2、2构造方法

        
    // 无参构造方法,使用默认构造器
	 public TreeMap() {   
        comparator = null; 
    }

	// 自定义比较器的构造方法
    public TreeMap(Comparator<? super K> comparator) { 
        this.comparator = comparator;
    }

	//将给定的Map对象的构造尾TreeMap,使用默认的构造器
    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null; 
        putAll(m);
    }

	//将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) {
        }
    }

3、核心方法

        put方法向TreeMap中添加一个元素,在编程方法上类似于数据结构中的二叉排序树节点的插入
        
    //put方法,向一颗TreeMap中添加指定元素
	public V put(K key, V value) {
		
		//获取根节点位置
        Entry<K,V> t = root;
		
		//如果TreeMap(根节点)为空
        if (t == null) {
            compare(key, key); // type (and possibly null) check

			//申请根节点,key值,value值,父节点的值
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
		
		
        int cmp;
        Entry<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);
        }
		
		//申请新节点插入上面遍历到的合适节点
        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;
    }
        get方法,根据指定的key获取其value值
    //根据key值获取指定的value
	public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
    }
	
	//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/qq_36441169/article/details/80829742