关于TreeMap你忽略了的那些

关于TreeMap你忽略了的那些

什么是TreeMap呢?

​ TreeMap,是从名字就可以看出来,是用树结构来实现Map映射的,它的底层实现用的是红黑树,从Java官方的TreeMap的部分代码就可以看得出来(有给节点染色):

private void fixAfterDeletion(Entry<K,V> x)方法(用于恢复树的平衡):

/** From CLR */
    private void fixAfterDeletion(Entry<K,V> x) {
        while (x != root && colorOf(x) == BLACK) {
            if (x == leftOf(parentOf(x))) {
                Entry<K,V> sib = rightOf(parentOf(x));

                if (colorOf(sib) == RED) {
                    setColor(sib, BLACK);
                    setColor(parentOf(x), RED);
                    rotateLeft(parentOf(x));
                    sib = rightOf(parentOf(x));
                }

                if (colorOf(leftOf(sib))  == BLACK &&
                    colorOf(rightOf(sib)) == BLACK) {
                    setColor(sib, RED);
                    x = parentOf(x);
                } else {
                    if (colorOf(rightOf(sib)) == BLACK) {
                        setColor(leftOf(sib), BLACK);
                        setColor(sib, RED);
                        rotateRight(sib);
                        sib = rightOf(parentOf(x));
                    }
                    setColor(sib, colorOf(parentOf(x)));
                    setColor(parentOf(x), BLACK);
                    setColor(rightOf(sib), BLACK);
                    rotateLeft(parentOf(x));
                    x = root;
                }
            } else { // symmetric
                Entry<K,V> sib = leftOf(parentOf(x));

                if (colorOf(sib) == RED) {
                    setColor(sib, BLACK);
                    setColor(parentOf(x), RED);
                    rotateRight(parentOf(x));
                    sib = leftOf(parentOf(x));
                }

                if (colorOf(rightOf(sib)) == BLACK &&
                    colorOf(leftOf(sib)) == BLACK) {
                    setColor(sib, RED);
                    x = parentOf(x);
                } else {
                    if (colorOf(leftOf(sib)) == BLACK) {
                        setColor(rightOf(sib), BLACK);
                        setColor(sib, RED);
                        rotateLeft(sib);
                        sib = leftOf(parentOf(x));
                    }
                    setColor(sib, colorOf(parentOf(x)));
                    setColor(parentOf(x), BLACK);
                    setColor(leftOf(sib), BLACK);
                    rotateRight(parentOf(x));
                    x = root;
                }
            }
        }

        setColor(x, BLACK);
    }

你知道TreeMap的用途吗?

​ 在说它的用途之前,就要先说一下它的性质了,它的性质其实和红黑树的性质几乎一样,因为它是用红黑树的每一个节点来存储一个Entry(即一个键值对),除此之外我们还知道,红黑树其实也是属于平衡二叉搜索树,既然如此,在进行插入节点的时候必然要对节点进行比较,如果相同则覆盖,一次来保证红黑树上每一个节点存储的值都是不一样的,众所周知的是Map中的Key都是唯一不重复的,因此综上所述,红黑树它在进行节点比较的时候,其实比较的是每一个Entry的Key。

小小总结一下:

  • 由红黑树实现,Key不重复且
  • 红黑树上的每一个Node都是一个Entry(即K-V对)
  • 为了保证红黑树的平衡,必须保证存储的Key是可比较的

​ 在知道了上面的知识后,我们再想想我们知道的 Set的数据结构,它存储的值也都是不重复的,是不是和我们上面说到的TreeMap的部分性质有点像呢?

​ 其实Java中的TreeSet就是用TreeMap实现的!下面来看看它的部分源码:

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
	private transient NavigableMap<E,Object> m;
	
	TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }
    
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }
    
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }
    
    //后面的代码省略....

}

​ 我们简单来看一下,从构造方法可以看出来,在初始化一个TreeSet的时候,其实是在初始化一个NavigableMap,而它其实就是TreeMap了。其实TreeSet是通过TreeMap将值存入到Key中实现的,所有的Value都是null。

为什么有了TreeMap,还要HashMap呢?

​ 相信这个问题是被人忽略做多的了,几乎没多少人去仔细想过,因为在探究为什么之前,需要你对红黑树以及哈希表具备一定的了解,但是本文想带你通过阅读文章来进行此问题的探究,因此,本篇会先告诉你HashMap诞生的缘由,以及TreeMap有哪些局限性,并由此为讲解HashMap开个头,好了,话不多说直接进入正题!

  • TreeMap的局限性

    之前在说TreeMap的性质的时候,有说到过K的可比较性,这其实便是TreeMap的局限所在,因为很多时候我们存储的数据并不具备可比较性,因此在进行存储的时候,那些进行比较的操纵其实就有点浪费性能了

  • 为什么需要HashMap

    知道了TreeMap的局限性之后,你大概就能猜出来HashMap为何诞生了的吧。其实HashMap是一种不考虑Key的可比较性的数据,并且它相比较TreeMap的O(log(n))的时间复杂度,可以达到O(1)级别,它的底层是采用哈希表来实现的

​ 在今后的文章中会对HashMap进行详细的讲解

上一篇:数据结构:红黑树的结构以及方法剖析 (下)


下一篇:AutoCAD 注册机未响应