TreeMap 实现了 SortedMap 和 NavigableMap 接口,所有本文还会记录 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. public boolean containsValue(Object value) {
  2. for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
  3. if (valEquals(value, e.value))
  4. return true;
  5. return false;
  6. }

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

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

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

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

  

9. successor(Entry e)

当 e 为 null 时,返回 null

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

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

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

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

当 e 为 null 时,返回 null

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

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

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

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

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

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

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

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

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

下面是一个完全二叉树的例子,其中满足完美二叉树的只有 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. public void putAll(Map<? extends K, ? extends V> map) {
  2. int mapSize = map.size();
  3. if (size==0 && mapSize!=0 && map instanceof SortedMap) {
  4. Comparator<?> c = ((SortedMap<?,?>)map).comparator();
  5. if (c == comparator || (c != null && c.equals(comparator))) {
  6. ++modCount;
  7. try {
  8. buildFromSorted(mapSize, map.entrySet().iterator(),
  9. null, null);
  10. } catch (java.io.IOException cannotHappen) {
  11. } catch (ClassNotFoundException cannotHappen) {
  12. }
  13. return;
  14. }
  15. }
  16. super.putAll(map);
  17. }

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. public void clear() {
  2. modCount++;
  3. size = 0;
  4. root = null;
  5. }

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

Jdk 版本: jdk1.8.0_31.jdk

[Java] TreeMap - 源代码学习笔记的更多相关文章

  1. TreeMap - 源代码学习笔记

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

  2. [Java] Collections - 源代码学习笔记

    Collection interface 集合接口 1. 在 Collections 体系中,接口 Collection 是根接口 2. 是指一组对象,这些对象被称为 Collection 的元素. ...

  3. [Java] LinkedList / Queue - 源代码学习笔记

    简单地画了下 LinkedList 的继承关系,如下图.只是画了关注的部分,并不是完整的关系图.本博文涉及的是 Queue, Deque, LinkedList 的源代码阅读笔记.关于 List 接口 ...

  4. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  5. Java多线程技术学习笔记(二)

    目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...

  6. Java安全防御学习笔记V1.0

    Java安全防御学习笔记V1.0http://www.docin.com/p-766808938.html

  7. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  8. java之jvm学习笔记三(Class文件检验器)

    java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...

  9. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

随机推荐

  1. 学习《Spring 3.x 企业应用开发实战》Day-1

    Day-1 记录自己学习spring的笔记 提要:根据<Spring 3.x 企业应用开发实战>开头一个用户登录的例子,按照上面敲的. 1.项目分层

  2. Python之路,Day16 - Django 进阶

    Python之路,Day16 - Django 进阶   本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...

  3. Day4 - Python基础4 迭代器、装饰器、软件开发规范

    Python之路,Day4 - Python基础4 (new版)   本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ...

  4. okhttp 基本介绍

    资料汇总 官网:http://square.github.io/okhttp/ 文档:https://github.com/square/okhttp/wiki GitHub:https://gith ...

  5. BestCoder 1st Anniversary

    Souvenir  Accepts: 1078  Submissions: 2366  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 26 ...

  6. .NET读取Excel

    1.代码 string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Path + ";Ext ...

  7. 查看sql server数据库各表占用空间大小

    exec sp_MSForEachTable @precommand=N' create table ##(id int identity,表名 sysname,字段数 int,记录数 int,保留空 ...

  8. 重拾C++ 基础知识总结(一)

    1.使用gcc编译c++文件报错 proc1.cc:(.text+0x14): undefined reference to `std::cout' C++程序使用gcc命令只能编译,不能链接库文件 ...

  9. Qt信号槽中槽函数为虚函数的一些感想

    有时候,在写connect的时候会去犹豫一个问题----我的槽函数到底需不需要为虚函数.这个问题在我每次写connect的时候我都会反问自己,因为确实,如果你不去深究里面的moc,你发现不了太多问题. ...

  10. C# 构造函数如何调用父类构造函数或其他构造函数

    class C : B{    C() : base(5)      // call base constructor B(5)    {  }    C(int i) : this()  // ca ...