[Java] TreeMap - 源代码学习笔记
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。因此,效率低。
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 返回树中最左下角的元素
final Entry<K,V> getFirstEntry() {
Entry<K,V> p = root;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}
getLastEntry 返回树中最右下角的元素
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 的祖先节点。
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 的祖先节点。
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 来实现的。
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
12. containsKey(Object) 同样也是基于 getEntry 来实现的
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
13. computeRedLevel(int) ,应用于复制一个 map 到当前为空的 TreeMap 的操作中。复制后的 TreeMap 应该是一棵完全二叉树(complete binary tree),通过将其中满足完美二叉树(perfect binary tree)部分的节点涂黑,则可以简单地实现红黑树的黑属性。
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 中。
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 即可
public void clear() {
modCount++;
size = 0;
root = null;
}
20. firstEntry 返回不可变的 Entry , getFirstEntry 则返回可变的 Entry。同样关系的还有:lastEntry 和 getLastEntry,lowerEntry 和 getLowerEntry, higherEntry 和 getHigherEntry。
Jdk 版本: jdk1.8.0_31.jdk
[Java] TreeMap - 源代码学习笔记的更多相关文章
- TreeMap - 源代码学习笔记
TreeMap 实现了 NavigableMap 接口,而NavigableMap 接口继承于 SortedMap接口. 所有本文还会记录 SortedMap 和 NavigableMap 的阅读笔记 ...
- [Java] Collections - 源代码学习笔记
Collection interface 集合接口 1. 在 Collections 体系中,接口 Collection 是根接口 2. 是指一组对象,这些对象被称为 Collection 的元素. ...
- [Java] LinkedList / Queue - 源代码学习笔记
简单地画了下 LinkedList 的继承关系,如下图.只是画了关注的部分,并不是完整的关系图.本博文涉及的是 Queue, Deque, LinkedList 的源代码阅读笔记.关于 List 接口 ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- Java安全防御学习笔记V1.0
Java安全防御学习笔记V1.0http://www.docin.com/p-766808938.html
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
随机推荐
- MyEclipse 安装SVN插件方法及插件下载地址
直接解压法 下载地址:http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240下载SVN插件:site-1.x.x. ...
- C++ | 调试 · 从汇编代码看i++和++i的区别
以int类型为例 C++编译器为++i生成的代码是 013E1375 mov eax,dword ptr [i] 013E1378 add eax, 013E137B mov dword ptr [i ...
- Linux: FTP服务原理及vsfptd的安装、配置
1.FTP 服务的安装# yum install -y vsftpd [root@rusky pub]# ls -l /etc/vsftpd/ total 20 -rw-------. 1 root ...
- NYOJ-520 最大素因子
这个题基本上就两个知识点, 一个素数筛选法求素数,另一个是求最大公因子, 不过确定最大素数在素数表中的位置时,要用到二分的思想,不然会超时,下面是具体代码的实现; #include <stdio ...
- Angular JS API
ng function angular.bind angular.bootstrap angular.copy angular.element angular.equals angular.exten ...
- (转)php 函数名称前的@有什么作用
如:$register_globals = @ini_get('register_globals'); 隐藏错误提示~如果ini_get('register_globals'); 语句错误的话`错误会 ...
- 64位操作系统下IIS报“试图加载格式不正确的程序”错误
缘由:在64位操作系统下IIS发布32位的项目,报“项目依赖的dll无法读取,试图加载格式不正确的程序”错误. 原因:程序集之间的通讯要么全是64位环境下的,要么全是32位环境下的.不能混编访问.不然 ...
- Objective-C内存管理与原理
尽管苹果在 iOS 5/ Mac OS X 10.7 开始导入ARC,利用 Xcode4.2 可以使用该机能.ARC就是自动引用计数,是一项为Objective - C程序在编译时提供自动内存管理的功 ...
- mysql的limit经典用法及优化
用法一 SELECT `keyword_rank`.* FROM `keyword_rank` WHERE (advertiserid='59') LIMIT 2 OFFSET 1; 比如这个 ...
- 35 Search Insert Position(找到数的位置Medium)
题目意思:在递增数组中找到目标数的位置,如果目标数不在数组中,返回其应该在的位置. 思路:折半查找,和相邻数比较,注意边界 class Solution { public: int searchIns ...