TreeMap内部实现简介

1、概述

TreeMap是Java内部实现比较复杂的集合类之一。与HashMap不一样,TreeMap的底层不是用哈希表实现的,而是用红黑树实现的。另外,HashMap存取元素的时间复杂度是O(1)的常量级,而TreeMap对元素的操作复杂度为O(log n)。虽然在操作性能方面,TreeMap不占优势,但是因为它使用红黑树(平衡二叉查找树)实现,所以它内部的元素都是排好序的。当需要查找的元素是排好序的,TreeMap的优势就体现出来了。

2、红黑树简介

首先,介绍一下红黑树的基本性质。红黑树不是一棵严格意义上的平衡树,因为它的高度差会大于1。了解一下它的性质就清楚了。

红黑树是一棵二叉树,它满足以下5个特性:

<1>每个节点的颜色是红色或黑色。

<2>根节点必须是黑色的。

<3>每个叶节点是黑色的(叶节点是指树尾端的NULL节点)。

<4>如果一个节点是红色的,那么它的子节点必须是黑色。即,不能有连续的红色节点。

<5>对于任意一个节点,从它到叶节点的每条路径包含相同数量的黑色节点。

由上述定义可知,红黑树是一棵相对平衡的二叉查找树。因为红黑树天生需要平衡,所以就可以避免一般的二叉查找树在极端情况(插入的数据已经排好序)失去平衡的情况。

3、TreeMap的Entry类

由于TreeMap包含了tree和Map的性质,它所包含的的Entry类应该有以下6个成员变量:

左子结点引用、右子节点引用、父节点引用、key、value、color。

在JDK中,Entry的具体定义如下:

static final class Entry<K,V> implements Map.Entry<K,V> {  
    K key;  
    V value;  
    Entry<K,V> left = null;  
    Entry<K,V> right = null;  
    Entry<K,V> parent;  
    boolean color = BLACK;  
  
    /** 
     * Make a new cell with given key, value, and parent, and with 
     * {@code null} child links, and BLACK color. 
     */  
    Entry(K key, V value, Entry<K,V> parent) {  
        this.key = key;  
        this.value = value;  
        this.parent = parent;  
    } 
}

4、TreeMap的put(key ,value)操作  
插入元素由put操作进行,主要包括两个过程,第一步是通过计算key找到插入元素的位置,如果新加入的key不存在直接插入;如果存在,那么就更新原节点的值。第二步是,因为插入新元素可能会破坏红黑树的属性,如果被破坏了,就要通过左右旋转等操作恢复红黑树的属性。具体代码如下:

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;  
    // 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();  
        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;  
}  


你可能感兴趣的:(java,数据结构)