zoukankan      html  css  js  c++  java
  • TreeSet和TreeMap部分源码解析

    首先我们看TreeSet的成员变量

    private transient NavigableMap<E,Object> m;
    private static final Object PRESENT = new Object();

    第一行的NavigebleMap接口它的实现有TreeMap

    第二行的Prensent马上就能知道它的作用了

    然后我们看它的构造函数

    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));
        }
    public TreeSet(Collection<? extends E> c) {
            this();
            addAll(c);
        }
     public TreeSet(SortedSet<E> s) {
            this(s.comparator());
            addAll(s);
        }

    我们能发现所有构造函数都是在初始化m,也就是NavigableMap

    接下来看几个它的函数

    public boolean add(E e) {
            return m.put(e, PRESENT)==null;
        }
    public boolean contains(Object o) {
            return m.containsKey(o);
        }
    public Iterator<E> iterator() {
            return m.navigableKeySet().iterator();
        }

    到此我们可以发现TreeSet是基于TreeMap实现的,它利用了Map的Key唯一,保证TreeSet的值唯一,即TreeSet的值被put到TreeMap的key上,而value是一个相同的Object

    知道了这一点,接下来我们开始进入TreeMap

    还是先看它的成员变量

    private final Comparator<? super K> comparator; //说明Key必须实现Comparator
    private transient Entry<K,V> root;//TreeMap是一颗红黑树,这是根结点
    private transient int size = 0;//大小
    private transient int modCount = 0;//操作次数

    它的每个结点是一个实现了Map.Entry<K,V>的Entry<K,V>,是它的内部类

    static final class Entry<K,V> implements Map.Entry<K,V> {
            K key;
            V value;
            Entry<K,V> left;
            Entry<K,V> right;
            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;
            }
            //................................................
    }

    接下来看它的构造函数

    public TreeMap() {
            comparator = null;
        }
    public TreeMap(Comparator<? super K> comparator) {
            this.comparator = comparator;
        }
    public TreeMap(Map<? extends K, ? extends V> m) {
            comparator = null;
            putAll(m);
        }
    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) {
            }
        }

    我们看到它的构造函数基本是在对comparator操作,和根据已有的结构添加为TreeMap(暂时忽略)

    然后我们看我们最常用的 put()

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

    用等号把源码分成了上中下三部分,上面的因为此时Comparator为null,所以调用了Compare(key,key)

    final int compare(Object k1, Object k2) {
            return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
                : comparator.compare((K)k1, (K)k2);
        }

    中间的部分明显看出就是根据已有的Comparator进行比较,和在树上添加新的值

    下面的部分有一句

    Comparable<? super K> k = (Comparable<? super K>) key;

    可以看出直接用了key的Comparator

    至此告一段落,做一个小总结

    TreeSet基于TreeMap实现,TreeMap底层是一个红黑树结构,TreeSet的值必须实现Comparator接口,TreeMap的key必须实现Comparator接口,他们根据Comparator决定每个值的位置

  • 相关阅读:
    docker删除常见命令
    测试网中用户添加docker yum源
    kafka 重新分配partition
    docker-compose常用命令
    docker 常用命令
    docker-compose部署ELK
    ELK全Dokcer 部署
    Harbor修改/data目录位置
    单机多es容器服务部署的网络模式
    C++使用模板类时出现LNK2019 unresolved external symbol错误.
  • 原文地址:https://www.cnblogs.com/blogofjzq/p/9235702.html
Copyright © 2011-2022 走看看