转自:http://www.fengfly.com/plus/view-213898-6.html
与Key相关的函数
TreeMap的firstKey()、lastKey()、lowerKey()、higherKey()、floorKey()、ceilingKey()原理都是类似的;下面以ceilingKey()来进行详细说明
ceilingKey(K key)的作用是“返回大于/等于key的最小的键值对所对应的KEY,没有的话返回null”,它的代码如下:
- public K ceilingKey(K key) {
- return keyOrNull(getCeilingEntry(key));
- }
ceilingKey()是通过getCeilingEntry()实现的。keyOrNull()的代码很简单,它是获取节点的key,没有的话,返回null。
- static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
- return e == null? null : e.key;
- }
getCeilingEntry(K 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);
- // 情况一:若“p的key” > key。
- // 若 p 存在左孩子,则设 p=“p的左孩子”;
- // 否则,返回p
- if (cmp < 0) {
- if (p.left != null)
- p = p.left;
- else
- return p;
- // 情况二:若“p的key” < key。
- } else if (cmp > 0) {
- // 若 p 存在右孩子,则设 p=“p的右孩子”
- 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;
- }
- // 情况三:若“p的key” = key。
- } else
- return p;
- }
- return null;
- }