声明:本文使用JDK1.8,如果有错希望指出
本文将简单介绍 JAVA 集合框架——TreeMap。TreeMap 集合是基于红黑树 的 NavigableMap 实现。该集合最重要的特性就是可排序 ,该映射可以根据 Map 的键的自然顺序排序,或者根据创建时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeMap 继承关系
源码分析 数据结构 TreeMap采用红黑树的数据结构来实现。树节点Entry实现了Map.Entry,采用内部类的方式实现:
1 2 3 4 5 6 7 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;
接下来看下 TreeMap 中支持红黑树的数据成员:
1 2 3 4 5 6 7 8 9 10 11 public class TreeMap <K,V> extends AbstractMap <K,V> implements NavigableMap <K,V>, Cloneable, java.io.Serializable{ private final Comparator<? super K> comparator; private transient Entry<K,V> root; private transient int size = 0 ; private transient int modCount = 0 ;
TreeMap 初始化与比较器 默认的构造器:
看源码注释,可以了解一些重点:
默认构建方法创建一棵空树
默认使用 key 的自然顺序构建有序树
除了使用 key 的默认比较器, TreeMap 还支持自定义比较器来初始化构造方法。
TreeMap 的 put 方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public V put (K key, V value) { Entry <K,V> t = root; if (t == null ) { compare(key, key); root = new Entry <>(key, value, null ); size = 1 ; modCount++; return null ; } int cmp; Entry<K,V> parent; 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 ; }
TreeMap 的 get 方法 TreeMap 的 get 方法其实只是一个简单的二叉树查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public V get (Object key) { Entry <K,V> p = getEntry(key); return (p==null ? null : p.value); } final Entry <K,V> getEntry (Object key) { if (comparator != null ) return getEntryUsingComparator(key); if (key == null ) throw new NullPointerException (); @SuppressWarnings("unchecked") Comparable <? super K> k = (Comparable<? super K>) key; Entry <K,V> p = root; 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 ; } final Entry <K,V> getEntryUsingComparator (Object key) { @SuppressWarnings("unchecked") K k = (K) key; Comparator <? super K> cpr = comparator; if (cpr != null ) { Entry <K,V> p = root; while (p != null ) { int cmp = cpr.compare(k, p.key); if (cmp < 0 ) p = p.left; else if (cmp > 0 ) p = p.right; else return p; } } return null ; }
TreeMap 的 remove 方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 public V remove (Object key) { Entry <K,V> p = getEntry(key); if (p == null ) return null ; V oldValue = p.value; deleteEntry(p); return oldValue; } private void deleteEntry (Entry<K,V> p) { modCount++; size--; if (p.left != null && p.right != null ) { Entry <K,V> s = successor(p); p.key = s.key; p.value = s.value; p = s; } Entry <K,V> replacement = (p.left != null ? p.left : p.right); if (replacement != null ) { replacement.parent = p.parent; if (p.parent == null ) root = replacement; else if (p == p.parent.left) p.parent.left = replacement; else p.parent.right = replacement; p.left = p.right = p.parent = null ; if (p.color == BLACK) fixAfterDeletion(replacement); } else if (p.parent == null ) { root = null ; } else { if (p.color == BLACK) fixAfterDeletion(p); if (p.parent != null ) { if (p == p.parent.left) p.parent.left = null ; else if (p == p.parent.right) p.parent.right = null ; p.parent = null ; } } } static <K,V> TreeMap.Entry <K,V> successor (Entry<K,V> t) { if (t == null ) return null ; else if (t.right != null ) { Entry <K,V> p = t.right; while (p.left != null ) p = p.left; return p; } else { Entry <K,V> p = t.parent; Entry <K,V> ch = t; while (p != null && ch == p.right) { ch = p; p = p.parent; } return p; } }
TreeMap 的 clear 方法 1 2 3 4 5 public void clear () { modCount++; size = 0 ; root = null ; }
Reference