TreeMap源码分析
TreeMap是基于红黑树来实现的,它是根据键的自然顺序,或者创建时提供的comparator来排序的。
1.属性
/** * The comparator used to maintain order in this tree map, or * null if it uses the natural ordering of its keys. * TreeMap中的映射排序是根据此comparator来排序的,如果此comparator为null,则根据键的自然顺序排序 * @serial */ private final Comparator<? super K> comparator; // 根元素 private transient Entry<K,V> root = null; /** * The number of entries in the tree
* 元素的数量 */ private transient int size = 0; /** * The number of structural modifications to the tree.
* TreeMap修改的次数 */ private transient int modCount = 0;
2.构造器
/** * Constructs a new, empty tree map, using the natural ordering of its * keys. All keys inserted into the map must implement the {@link * Comparable} interface. Furthermore, all such keys must be * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw * a {@code ClassCastException} for any keys {@code k1} and * {@code k2} in the map. If the user attempts to put a key into the * map that violates this constraint (for example, the user attempts to * put a string key into a map whose keys are integers), the * {@code put(Object key, Object value)} call will throw a * {@code ClassCastException}. */ public TreeMap() { comparator = null; } /** * Constructs a new, empty tree map, ordered according to the given * comparator. All keys inserted into the map must be <em>mutually * comparable</em> by the given comparator: {@code comparator.compare(k1, * k2)} must not throw a {@code ClassCastException} for any keys * {@code k1} and {@code k2} in the map. If the user attempts to put * a key into the map that violates this constraint, the {@code put(Object * key, Object value)} call will throw a * {@code ClassCastException}. * * @param comparator the comparator that will be used to order this map. * If {@code null}, the {@linkplain Comparable natural * ordering} of the keys will be used.
* 构造一个空的TreeMap,根据指定的comparator来排序 */ public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } /** * Constructs a new tree map containing the same mappings as the given * map, ordered according to the <em>natural ordering</em> of its keys. * All keys inserted into the new map must implement the {@link * Comparable} interface. Furthermore, all such keys must be * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw * a {@code ClassCastException} for any keys {@code k1} and * {@code k2} in the map. This method runs in n*log(n) time. * * @param m the map whose mappings are to be placed in this map * @throws ClassCastException if the keys in m are not {@link Comparable}, * or are not mutually comparable * @throws NullPointerException if the specified map is null
* 构造一个TreeMap,包含给定的Map,按照key的自然顺序排序,key要实现Comparable接口 */ public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } /** * Constructs a new tree map containing the same mappings and * using the same ordering as the specified sorted map. This * method runs in linear time. * * @param m the sorted map whose mappings are to be placed in this map, * and whose comparator is to be used to sort this map * @throws NullPointerException if the specified map is null
* 构造一个TreeMap,包含指定的Map,按照给定的SortedMap的排序规则进行排序 */ 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) { } }
3.方法
3.1:V put(K key,V value):将指定值与此映射中的指定键进行关联。如果该映射以前包含此键的映射关系,那么将替换旧值
插入操作可以分为两步:一是将该TreeMap看做一个二叉树来操作,找到将要插入的位置,然后进行插入操作。二是当插入操作完成后,为了保证红黑树的特性,需要对红黑树调整:节点旋转和颜色改变
public V put(K key, V value) { Entry<K,V> t = root;
// 如果根节点为null,那么这个插入的数据将是根节点 if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; }
// key值比较大小返回的比较结果 int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator;
// Comparator不为空的情况下,使用comparator来比较key值的大小,同时获取新插入节点的父节点parent 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); }
// Comparator为null的情况下,使用key的自然顺序进行排序,同时获取新插入节点的父节点parent 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; else parent.right = e;
// 为了保证红黑树的特性,需要进行红黑树调整:节点旋转和颜色改变 fixAfterInsertion(e); size++; modCount++; return null; }
进入fixAfterInsertion方法:进行节点旋转和颜色改变。可以参照我的另一篇文章:红黑树详解
private void fixAfterInsertion(Entry<K,V> x) { x.color = RED; while (x != null && x != root && x.parent.color == RED) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { Entry<K,V> y = rightOf(parentOf(parentOf(x))); if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == rightOf(parentOf(x))) { x = parentOf(x); rotateLeft(x); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateRight(parentOf(parentOf(x))); } } else { Entry<K,V> y = leftOf(parentOf(parentOf(x))); if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == leftOf(parentOf(x))) { x = parentOf(x); rotateRight(x); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateLeft(parentOf(parentOf(x))); } } } root.color = BLACK; }
3.2:V get(Object key):返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null
。
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)
// 如果Comparator不为null,则比较器使用Comparator,来获取对应的Value return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root;
// 否则使用key的自然排序来获取Value 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; }
3.3 remove (Object key):如果此 TreeMap 中存在该键的映射关系,则将其删除。