版权声明:尊重博主原创文章,转载请注明出处哦~http://blog.csdn.net/eson_15/article/details/51217741
前面讨论完了HashMap和HashTable的源码,这一节我们来讨论一下TreeMap。先从整体上把握TreeMap,然后分析其源码,深入剖析TreeMap的实现。
1. TreeMap简介
TreeMap是一个有序的key-value集合,它内部是通过红-黑树实现的,如果对红-黑树不太了解,请先参考下这篇博文:红-黑树。下面我们先来看看TreeMap的继承关系:
- java.lang.Object
- ↳ java.util.AbstractMap<K, V>
- ↳ java.util.TreeMap<K, V>
- public class TreeMap<K,V>
- extends AbstractMap<K,V>
- implements NavigableMap<K,V>, Cloneable, java.io.Serializable {}
TreeMap是基于红-黑树实现的,该映射根据其key的自然顺序进行排序,或者根据用户创建映射时提供的Comarator进行排序,另外,TreeMap是非同步的。
我们先总览一下TreeMap都有哪些API:
- Entry<K, V> ceilingEntry(K key)
- K ceilingKey(K key)
- void clear()
- Object clone()
- Comparator<? super K> comparator()
- boolean containsKey(Object key)
- NavigableSet<K> descendingKeySet()
- NavigableMap<K, V> descendingMap()
- Set<Entry<K, V>> entrySet()
- Entry<K, V> firstEntry()
- K firstKey()
- Entry<K, V> floorEntry(K key)
- K floorKey(K key)
- V get(Object key)
- NavigableMap<K, V> headMap(K to, boolean inclusive)
- SortedMap<K, V> headMap(K toExclusive)
- Entry<K, V> higherEntry(K key)
- K higherKey(K key)
- boolean isEmpty()
- Set<K> keySet()
- Entry<K, V> lastEntry()
- K lastKey()
- Entry<K, V> lowerEntry(K key)
- K lowerKey(K key)
- NavigableSet<K> navigableKeySet()
- Entry<K, V> pollFirstEntry()
- Entry<K, V> pollLastEntry()
- V put(K key, V value)
- V remove(Object key)
- int size()
- SortedMap<K, V> subMap(K fromInclusive, K toExclusive)
- NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive)
- NavigableMap<K, V> tailMap(K from, boolean inclusive)
- SortedMap<K, V> tailMap(K fromInclusive)
2. TreeMap的源码分析(基于JDK1.7)
2.1 存储结构
由于TreeMap是基于红黑树实现的,所以其内部维护了一个红-黑树的数据结构,每个key-value对也存储在一个Entry里,只不过这个Entry和前面HashMap或者HashTable中的Entry不同,TreeMap的Entry其实是红-黑树的一个节点。我们来看一下TreeMap中的Entry定义:
- private transient Entry<K,V> root = null;
2.2 Entry实体类和相关方法
先看一下Entry实体类:
- private static final boolean RED = false;
- private static final boolean BLACK = true;
- //就是一个红黑树的节点
- static final class Entry<K,V> implements Map.Entry<K,V> {
- K key;
- V value;
- Entry<K,V> left = null; //左子节点
- Entry<K,V> right = null; //右子节点
- Entry<K,V> parent; //父节点
- boolean color = BLACK; //树的颜色,默认为黑色
- Entry(K key, V value, Entry<K,V> parent) { //构造方法
- this.key = key;
- this.value = value;
- this.parent = parent;
- }
- public K getKey() { //获得key
- return key;
- }
- public V getValue() { //获得value
- return value;
- }
- public V setValue(V value) { //设置value
- V oldValue = this.value;
- this.value = value;
- return oldValue;
- }
- public boolean equals(Object o) { //key和value均相等才返回true
- if (!(o instanceof Map.Entry))
- return false;
- Map.Entry<?,?> e = (Map.Entry<?,?>)o;
- return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
- }
- public int hashCode() { //计算hashCode
- int keyHash = (key==null ? 0 : key.hashCode());
- int valueHash = (value==null ? 0 : value.hashCode());
- return keyHash ^ valueHash;
- }
- public String toString() { //重写toString方法
- return key + "=" + value;
- }
- }
- public Map.Entry<K,V> firstEntry() {
- return exportEntry(getFirstEntry());
- }
- //获得TreeMap里第一个节点(即根据key排序最小的节点),如果TreeMap为空,返回null
- final Entry<K,V> getFirstEntry() {
- Entry<K,V> p = root;
- if (p != null)
- while (p.left != null)
- p = p.left;
- return p;
- }
- static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
- return (e == null) ? null :
- new AbstractMap.SimpleImmutableEntry<>(e);
- }
- public static class SimpleImmutableEntry<K,V>
- implements Entry<K,V>, java.io.Serializable
- {
- private static final long serialVersionUID = 7138329143949025153L;
- private final K key;
- private final V value;
- public SimpleImmutableEntry(K key, V value) { //通过key和value初始化对象
- this.key = key;
- this.value = value;
- }
- public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) { //通过传进来一个Entry初始化对象
- this.key = entry.getKey();
- this.value = entry.getValue();
- }
- public K getKey() {
- return key;
- }
- public V getValue() {
- return value;
- }
- public V setValue(V value) { //!!!关键地方在这里,不能setValue,否则会抛出UnsupportedOperationException异常
- throw new UnsupportedOperationException();
- }
- public boolean equals(Object o) {
- if (!(o instanceof Map.Entry))
- return false;
- Map.Entry e = (Map.Entry)o;
- return eq(key, e.getKey()) && eq(value, e.getValue());
- }
- public int hashCode() {
- return (key == null ? 0 : key.hashCode()) ^
- (value == null ? 0 : value.hashCode());
- }
- //重写了toString方法,返回key=value形式
- public String toString() {
- return key + "=" + value;
- }
- }
- /*********************** 与Entry相关的方法 ******************************/
- //获取TreeMap中键为key对应的节点
- final Entry<K,V> getEntry(Object key) {
- // 若比较器不为null,则通过getEntryUsingComparator来获得
- if (comparator != null)
- return getEntryUsingComparator(key);
- if (key == null)
- throw new NullPointerException();
- 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;
- }
- //使用比较器获得与key对应的Entry
- final Entry<K,V> getEntryUsingComparator(Object key) {
- 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;
- }
- /*--------------------------------------------------------*/
- public Map.Entry<K,V> firstEntry() {
- return exportEntry(getFirstEntry());
- }
- //获得TreeMap里第一个节点(即根据key排序最小的节点),如果TreeMap为空,返回null
- final Entry<K,V> getFirstEntry() {
- Entry<K,V> p = root;
- if (p != null)
- while (p.left != null)
- p = p.left;
- return p;
- }
- /*-----------------------------------------------*/
- public Map.Entry<K,V> lastEntry() {
- return exportEntry(getLastEntry());
- }
- //获得TreeMap里最后一个节点(根据key排序最大的节点),如果TreeMap为空,返回null
- final Entry<K,V> getLastEntry() {
- Entry<K,V> p = root;
- if (p != null)
- while (p.right != null)
- p = p.right;
- return p;
- }
- /*------------------------------------------------*/
- //弹出第一个节点,即删除
- public Map.Entry<K,V> pollFirstEntry() {
- Entry<K,V> p = getFirstEntry();
- Map.Entry<K,V> result = exportEntry(p);
- if (p != null)
- deleteEntry(p);
- return result;
- }
- //弹出最后一个节点,即删除
- public Map.Entry<K,V> pollLastEntry() {
- Entry<K,V> p = getLastEntry();
- Map.Entry<K,V> result = exportEntry(p);
- if (p != null)
- deleteEntry(p);
- return result;
- }
- /*-------------------------------------------------*/
- public Map.Entry<K,V> floorEntry(K key) {
- return exportEntry(getFloorEntry(key));
- }
- public Map.Entry<K,V> ceilingEntry(K key) {
- return exportEntry(getCeilingEntry(key));
- }
- //获取TreeMap中不小于key的最小的节点;
- //若不存在(即TreeMap中所有节点的键都比key大),就返回null
- final Entry<K,V> getCeilingEntry(K key) {
- Entry<K,V> p = root;
- while (p != null) {
- int cmp = compare(key, p.key);
- if (cmp < 0) { //情况1. 若p.key > key
- if (p.left != null) //若p有左子节点
- p = p.left; //往左下走
- else
- return p; //否则返回p
- } else if (cmp > 0) { //情况2:p.key < key
- if (p.right != null) {
- p = p.right;
- } else {
- // 若 p 不存在右孩子,则找出 p 的后继节点,并返回
- // 注意:这里返回的 “p的后继节点”有2种可能性:第一,null;第二,TreeMap中大于key的最小的节点。
- // 理解这一点的核心是,getCeilingEntry是从root开始遍历的。
- // 若getCeilingEntry能走到这一步,那么,它之前“已经遍历过的节点的key”都 > key。
- // 能理解上面所说的,那么就很容易明白,为什么“p的后继节点”又2种可能性了。
- Entry<K,V> parent = p.parent;
- Entry<K,V> ch = p;
- while (parent != null && ch == parent.right) {
- ch = parent;
- parent = parent.parent;
- }
- return parent;
- }
- } else //情况3:p.key = key
- return p;
- }
- return null;
- }
- // 获取TreeMap中不大于key的最大的节点;
- // 若不存在(即TreeMap中所有节点的键都比key小),就返回null
- // getFloorEntry的原理和getCeilingEntry类似,这里不再多说。
- final Entry<K,V> getFloorEntry(K key) {
- Entry<K,V> p = root;
- while (p != null) {
- int cmp = compare(key, p.key);
- if (cmp > 0) {
- if (p.right != null)
- p = p.right;
- else
- return p;
- } else if (cmp < 0) {
- if (p.left != null) {
- p = p.left;
- } else {
- Entry<K,V> parent = p.parent;
- Entry<K,V> ch = p;
- while (parent != null && ch == parent.left) {
- ch = parent;
- parent = parent.parent;
- }
- return parent;
- }
- } else
- return p;
- }
- return null;
- }
- /*--------------------------------------------------*/
- public Map.Entry<K,V> lowerEntry(K key) {
- return exportEntry(getLowerEntry(key));
- }
- public Map.Entry<K,V> higherEntry(K key) {
- return exportEntry(getHigherEntry(key));
- }
- // 获取TreeMap中大于key的最小的节点。
- // 若不存在,就返回null。
- // 请参照getCeilingEntry来对getHigherEntry进行理解。
- final Entry<K,V> getLowerEntry(K key) {
- Entry<K,V> p = root;
- while (p != null) {
- int cmp = compare(key, p.key);
- if (cmp > 0) {
- if (p.right != null)
- p = p.right;
- else
- return p;
- } else {
- if (p.left != null) {
- p = p.left;
- } else {
- Entry<K,V> parent = p.parent;
- Entry<K,V> ch = p;
- while (parent != null && ch == parent.left) {
- ch = parent;
- parent = parent.parent;
- }
- return parent;
- }
- }
- }
- return null;
- }
- // 获取TreeMap中小于key的最大的节点。
- // 若不存在,就返回null。
- // 请参照getCeilingEntry来对getLowerEntry进行理解。
- final Entry<K,V> getHigherEntry(K key) {
- Entry<K,V> p = root;
- while (p != null) {
- int cmp = compare(key, p.key);
- if (cmp < 0) {
- if (p.left != null)
- p = p.left;
- else
- return p;
- } else {
- if (p.right != null) {
- p = p.right;
- } else {
- Entry<K,V> parent = p.parent;
- Entry<K,V> ch = p;
- while (parent != null && ch == parent.right) {
- ch = parent;
- parent = parent.parent;
- }
- return parent;
- }
- }
- }
- return null;
- }
- /*---------------------------------------------------*/
2.3 成员属性的构造方法
分析完了Entry实体相关的源码后,我们来看看TreeMap里的成员属性。
- /********************* 成员属性 ****************************/
- private final Comparator<? super K> comparator; //比较器
- private transient Entry<K,V> root = null; //实体对象
- private transient int size = 0; //红黑树节点个数,即Entry数
- 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) { //带Map的构造方法,Map会为TreeMap的子类
- comparator = null;
- putAll(m);
- }
- ////带sortedMap的构造方法,sortedMap会为TreeMap的子类
- 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) {
- }
- }
- public void putAll(Map<? extends K, ? extends V> map) {
- int mapSize = map.size();//获取map的大小
- //如果TreeMap大小是0,且map的大小不为0,且map是已排序的key-value对,才执行下面的程序
- if (size==0 && mapSize!=0 && map instanceof SortedMap) {
- Comparator c = ((SortedMap)map).comparator();
- if (c == comparator || (c != null && c.equals(comparator))) {
- ++modCount;
- try {
- buildFromSorted(mapSize, map.entrySet().iterator(),
- null, null);
- } catch (java.io.IOException cannotHappen) {
- } catch (ClassNotFoundException cannotHappen) {
- }
- return;
- }
- }
- //否则调用AbstractMap中的putAll()
- //AbstractMap中的putAll()又会调用TreeMap的put()方法
- super.putAll(map);
- }
在putAll方法内部,会先进行判断,如果TreeMap是空的,且传进来的map符合条件,则执行if内的语句,然后调用buildFromSorted方法(后面放到源码中分析)来put进去,否则调用父类的putAll方法,父类的putAll方法则直接调用TreeMap的put方法。
由于TreeMap的源码比较多,这里先写到这,后面的源码分析放到下一篇博客中写:java集合框架11——TreeMap和源码分析(二)。
如有错误之处,欢迎留言指正~
_____________________________________________________________________________________________________________________________________________________
-----乐于分享,共同进步!