TreeMap的源码学习java
一)、TreeMap的特色算法
根据key值进行排序。数据结构
二)、按key值排序的两种排序算法实现ide
1).在构造方法中传入比较器性能
public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } 比较器comparator实现Comparator接口,实现compare(T o1, T o2)方法; int compare(T o1, T o2);
2).key值实现Comparable接口,重写 compareTo(key k)方法学习
T implements Comparable<T>{ @override public int compareTo(T k) }
注: 对于TreeMap而言,排序是一个必须进行的过程,要正常使用TreeMap必须制 定排序规则,加入Comparator或key对象实现Comparable接口,若没有制定 比较规则则会抛出java.lang.ClassCastException。this
由于String对象默认实现了Comparable接口,实现了comparaTo方法,使用String类型做为key值,不用进行排序。code
三)、TreeMap的数据结构orm
红黑树:Entry<k, v>对象
Entry<k ,v> 对象的属性:
K key; V value; Entry<k, v> left; Entry<k, v> right; Entry<k, v> parent; boolean color = BLACK;
红黑树是一种平衡查找树.
四)、TreeMap的主要属性
//比较器 private final Comparator<? super K> comparator; //树的根节点 private transient Entry<K,V> root; //节点个数即元素个数 private transient int size = 0; //修改次数 private transient int modCount = 0; //用于构造红黑树 private static final boolean RED = false; private static final boolean BLACK = true;
五)、TreeMap的put(K key, V value)方法
步骤:
1).获取root节点,判断是否第一次添加元素 ,如果第一次添加元素则将该元素设为根节点。
2).如若不是第一次添加,根据key值,调用比较规则从根节点开始比较左右子树直至到达叶子节点,根据key的比较结果决定放置到叶子节点的左树位置或右树位置,> 0放置右树, < 0 放置右树。
3).fixAfterInsertion修改插入元素后树的结构,转为红黑树。
TreeMap<String, String> treeMap = new TreeMap<>(); treeMap.put("a","v"); 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); } //使用key 实现Comparable的compareTo()规则 else { if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") /** 若是Key没有加入比较器或没有实现Comparable这里就 抛出java.lang,ClassCastException */ Comparable<? super K> k = (Comparable<? super K>) key; //一直比较左右子树的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); //< 0 做为节点的左子树 if (cmp < 0) parent.left = e; // > 0 做为节点的右子树 else parent.right = e; //调整插入元素的树结构,转为红黑树 fixAfterInsertion(e); size++; modCount++; return null; }
六)、TreeMap的get(K key)方法
步骤:
1).获取根节点
2).从根节点开始比较左右子树的key值
3).若树中某一节点的key值与查找的key值相等,则返回对应的Entry<k, v>对象
treeMap.get("a"); public V get(Object key) { Entry<K,V> p = getEntry(key); return (p==null ? null : p.value); } final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance //判断是否存在比较器,如有比较器,则使用比较器的比较规则 if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") //没有比较器使用comparale的compareTo()规则 Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; //从根节点遍历左右子树,若key值相等,则返回当前节点对象 while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; }
注:TreeMap的功能比HashMap的功能强大, 实现了sortedMap接口,能够对元素 进行排序,单TreeMap的性能却略低于HashMap,当须要对集合进行排序操做可以使用TreeMap.