TreeSet和TreeMap部分源码解析
Posted blogofjzq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;//操作次数
接下来看它的构造函数
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决定每个值的位置
以上是关于TreeSet和TreeMap部分源码解析的主要内容,如果未能解决你的问题,请参考以下文章