zoukankan      html  css  js  c++  java
  • TreeSet与TreeMap的源码分析 JDK7

    TreeSet存储原则是:不可重复,有序的。

    public TreeSet() {
            this(new TreeMap<E,Object>());
        }
        public TreeSet(Comparator<? super E> comparator) {
            this(new TreeMap<>(comparator));
        }

    上面是TreeSet常用的两个构造函数。

    底层实现也就是TreeMap。

     TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }
        /**
         * The backing map.
         */
        private transient NavigableMap<E,Object> m;
    
        // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();

    维护了上面两个变量。

    add方法

    public boolean add(E e) {
            return m.put(e, PRESENT)==null;
        }

    因为TreeMap存储的是键值对,因此他将要保存的元素作为key,以一个常量作为值保存到TreeMap中。

    这就是为什么TreeSet保存的元素是不可重复的了,因为TreeMap的键不可以重复。

    到这里TreeSet也差不多分析完了,主要还是分析TreeMap,因为实现在他里面。

    TreeMap常用构造函数:

        public TreeMap(Comparator<? super K> comparator) {
            this.comparator = comparator;
        }
        public TreeMap() {
            comparator = null;
        }

    这里Comparator是一个比较器,这就是为什么TreeSet是有序的原因了。

        private final Comparator<? super K> comparator;
    
        private transient Entry<K,V> root = null;

    上面两个主要变量,一个是比较器,一个是根。这个根是因为数据结构而设计的,一种红黑树或者叫二叉树的一种数据结构。TreeMap也是根据这个数据结构而设计的。

    好,我们来看看添加元素的真面目吧。

    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);//根节点就是第一个添加进来的元素,前一个节点为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;//此时,parent元素的值最小,新元素的值比parent还小,放在parent左边
            else
                parent.right = e;//此时,parent元素的值最最大,新元素的值比parent还大,放在parent右边
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }

    好,现在元素放进去了,要取出来吧。使用iterator()方法。

    //TreeSet
    public Iterator<E> iterator() {
            return m.navigableKeySet().iterator();
        }

    TreeSet的iterator方法是调用了TreeMap的方法。这个方法是从JDK1.6开始有的

     /**
         * @since 1.6
         */
        public NavigableSet<K> navigableKeySet() {
            KeySet<K> nks = navigableKeySet;
            return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
        }

    实际上就是调用了KeySet的iterator方法。

  • 相关阅读:
    开发Django项目01
    本地安装python2.x和python3.x双版本之后怎么使用pip
    python3.x并发编程
    centos6.8安装JDK1.8教程
    yum安装MySQL指定版本
    python爬虫爬取get请求的页面数据代码样例
    python网络爬虫学习笔记
    python通过get方式,post方式发送http请求和接收http响应-urllib urllib2
    CentOS7.5安装python-pip报Error: Nothing to do解决方法
    文件操作
  • 原文地址:https://www.cnblogs.com/hjy9420/p/5041666.html
Copyright © 2011-2022 走看看