TreeMap - 源代码学习笔记

TreeMap 实现了 NavigableMap 接口,而NavigableMap 接口继承于 SortedMap接口。 所有本文还会记录 SortedMap 和 NavigableMap 的阅读笔记。

SortedMap

1. 排序的比较应该和 equals(Object) 保持一致

2. 应该提供四种“标准”的构造器

  1). 无参构造器

  2). 带一个 Comparator 为参数的构造器

  3). 带一个 Map 为参数的构造器

  4). 带一个 SortedMap 为参数的构造器

3.  subMap ,  headMap ,  tailMap ,  KeySet ,  values,  entrySet  等方法返回的 Map 或 Set 和 SortedMap 本身使用同一份数据,所以对 subMap 返回的 Map 进行修改,同样会反映到 SortedMap 上。

 

NavigableMap

1. lowerEntry, floorEntry, ceilingEntry, higherEntry 分别返回 小于、小于或等于,大于或等于,以及大于给定 key 的 Map.Entry。这类型的方法用于定位离目标给定值最近的元素。

2. 增长序 map 的操作比递减序的 map 的操作要快。

3. 返回 entry 的方法返回的是那一刻的 entry 快照,所以通常不支持 Entry.setValue 方法。

例如, TreeMap 实现 NavigableMap 的 firstEntry,返回会的就是根据给定 entry 的 key, value 新建的不可变 

SimpleImmutableEntry 对象。

4. pollFirstEntry 删除并返回第一个元素

 

TreeMap

1. 基于红黑树的实现

2. 根据自然序,或者给定的比较器是内部元素保持有序。

3. 提供复杂度为 log(n) 的 containsKey, get, put, remove 操作

4. itertator 采用 fast-fail 机制

5. values 继承于 Collection, EntrySet 和 KeySet 则继承于 Set

6. DeletionEntry 删除指定的元素,fixAfterDeletion 对删除后的树节点进行再平衡,使得 TreeMap 保持红黑树的特性。

7. containsValue(Object) 通过遍历所有元素,来判断是否包含指定的值为 value。因此,效率低。

1
2
3
4
5
6
public  boolean  containsValue(Object value) {
     for  (Entry<K,V> e = getFirstEntry(); e !=  null ; e = successor(e))
         if  (valEquals(value, e.value))
             return  true ;
     return  false ;
}

8. getFirstEntry 返回树中最左下角的元素

1
2
3
4
5
6
7
final  Entry<K,V> getFirstEntry() {
     Entry<K,V> p = root;
     if  (p !=  null )
         while  (p.left !=  null )
             p = p.left;
     return  p;
}

getLastEntry 返回树中最右下角的元素

1
2
3
4
5
6
7
final  Entry<K,V> getLastEntry() {
     Entry<K,V> p = root;
     if  (p !=  null )
         while  (p.right !=  null )
             p = p.right;
     return  p;
}

  

9. successor(Entry e) 

当 e 为 null 时,返回 null

当 e 有右子节点时,则返回右子节点的最左下角后代节点

当 e 没有右子节点时,返回一个离 e 最近的祖先节点,该祖先节的左孩子也是 e 的祖先节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
     }
}

10. prodecessor(Entry e) 和 successor(Entry e) 思路相似。

当 e 为 null 时,返回 null

当 e 有左子节点时,则返回左子节点的最右下角后代节点

当 e 没有左子节点时,返回一个离 e 最近的祖先节点,该祖先节的右孩子也是 e 的祖先节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static  <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
     if  (t ==  null )
         return  null ;
     else  if  (t.left !=  null ) {
         Entry<K,V> p = t.left;
         while  (p.right !=  null )
             p = p.right;
         return  p;
     else  {
         Entry<K,V> p = t.parent;
         Entry<K,V> ch = t;
         while  (p !=  null  && ch == p.left) {
             ch = p;
             p = p.parent;
         }
         return  p;
     }
}

11. get(Object):V 和 getEntry(Object):Entry 的不同点在于,前者返回 V, 而后者返回 Entry。获取的算法一样,因为 get 是基于 getEntry 来实现的。

1
2
3
4
public  V get(Object key) {
     Entry<K,V> p = getEntry(key);
     return  (p== null  null  : p.value);
}

12. containsKey(Object) 同样也是基于 getEntry 来实现的

1
2
3
public  boolean  containsKey(Object key) {
     return  getEntry(key) !=  null ;
}

13. computeRedLevel(int) ,应用于复制一个 map 到当前为空的 TreeMap 的操作中。复制后的 TreeMap 应该是一棵完全二叉树(complete binary tree),通过将其中满足完美二叉树(perfect binary tree)部分的节点涂黑,则可以简单地实现红黑树的黑属性

1
2
3
4
5
6
private  static  int  computeRedLevel( int  sz) {
     int  level =  0 ;
     for  ( int  m = sz -  1 ; m >=  0 ; m = m /  2  1 )
         level++;
     return  level;
}

下面是一个完全二叉树的例子,其中满足完美二叉树的只有 0 - 7 个节点,也就是 0 - 2 层。0 - 2 层的节点全部涂黑色,最后一层则全部涂红色。则最方便地满足红黑树的特性。

14. buildFromSorted, 采用递归的思路,先构建后节点的左子树,在构建好节点的右子树,最后和节点组合成一个完整的子树。

15. putAll(Map),

当 TreeMap 没有元素,Map 是一个 sortMap, 并且 Map 的比较器等于 TreeMap 的比较器,则采用 buildFormSorted 来构建 TreeMap。

否则,将 Map 中每个 mapping,通过调用 put(K, V) 来插入 TreeMap 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  void  putAll(Map<?  extends  K, ?  extends  V> map) {
     int  mapSize = map.size();
     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 ;
         }
     }
     super .putAll(map);
}

16. getEntry, getEntryUsingComparator, getCeilingEntry, getFloorEntry, getHigherEntry, getLowerEntry 都是基于二分查找思路来实现元素操作。

17. put(K, V)

当已存在 key 和 K 相等的 Entry, 则直接更新这个 Entry 的 value 值。

否则,插入新的 Entry ,然后自平衡树结构。

18. remove(Object),删除指定节点,然后自平衡树结构

19. clear(), 将 root 至 null 即可

1
2
3
4
5
public  void  clear() {
     modCount++;
     size =  0 ;
     root =  null ;
}

20.  firstEntry 返回不可变的 Entry , getFirstEntry 则返回可变的 Entry。同样关系的还有:lastEntry 和 getLastEntry,lowerEntry 和 getLowerEntry, higherEntry 和 getHigherEntry。

转载于:https://www.cnblogs.com/Pjson/p/8745884.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值