java源码分析之TreeMap深入篇

本文深入探讨了Java中的TreeMap数据结构,详细介绍了包括Values、EntrySet、KeySet在内的十三个内部类以及相关迭代器。重点讨论了PrivateEntryIterator、EntrySet、KeySet、NavigableSubMap等类的实现细节,并解析了TreeMap中树的遍历次序。通过对这些内部类的分析,有助于理解TreeMap的复杂实现。
摘要由CSDN通过智能技术生成

TreeMap有Values、EntrySet、KeySet、PrivateEntryIterator、EntryIterator、ValueIterator、KeyIterator、DescendingKeyIterator、NavigableSubMap、AscendingSubMap、DescendingSubMap、SubMap、Entry共十三个内部类。Entry是在TreeMap中用于表示树的节点的内部类,已经在《java源码分析之TreeMap基础篇》中分析过。下面逐一介绍上面的内部类以及TreeMap中提供的和内部类相关的方法。

     先看Values。

复制代码
 1 // 从类的定义可以看出,Values是一个集合类
 2 class Values extends AbstractCollection<V> {
 3     // 提供集合类Values的迭代器
 4     public Iterator<V> iterator() {
 5         return new ValueIterator(getFirstEntry());
 6     }
 7     // 返回TreeMap中保存的节点数
 8     public int size() {
 9         return TreeMap.this.size();
10     }
11     // 判断TreeMap中是否存在Value为o的节点
12     public boolean contains(Object o) {
13         return TreeMap.this.containsValue(o);
14     }
15     // 删除一个对象
16     public boolean remove(Object o) {
17         // 遍历TreeMap
18         for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) {
19             // 寻找值相等的节点
20             if (valEquals(e.getValue(), o)) {
21                 // 删除找到的节点
22                 deleteEntry(e);
23                 return true;
24             }
25         }
26         return false;
27     }
28     // 清空TreeMap
29     public void clear() {
30         TreeMap.this.clear();
31     }
32 }
复制代码

     Values类实际上是一个代理,多数方法都是调用TreeMap的方法。在Values的iterator()方法中返回了一个ValuesIterator对象,下面来看和迭代器相关的内部类。PrivateEntryIterator是TreeMap中和迭代器相关的类的基础,以下是PrivateEntryIterator的内容。

复制代码
 1 abstract class PrivateEntryIterator<T> implements Iterator<T> {
 2     // 指向next的引用
 3 Entry<K,V> next;
 4 // 保留对上一次返回节点的引用
 5     Entry<K,V> lastReturned;
 6     int expectedModCount;
 7     // 构造方法,lastReturned置空,next指向传入的节点
 8     PrivateEntryIterator(Entry<K,V> first) {
 9         expectedModCount = modCount;
10         lastReturned = null;
11         next = first;
12     }
13     // 判断是否还有下一个节点
14     public final boolean hasNext() {
15         return next != null;
16     }
17     // 返回下一个节点
18     final Entry<K,V> nextEntry() {
19         Entry<K,V> e = next;
20         if (e == null)
21             throw new NoSuchElementException();
22         if (modCount != expectedModCount)
23             throw new ConcurrentModificationException();
24         // next移动到它的继承者
25         next = successor(e);
26         // 记录被返回的节点
27         lastReturned = e;
28         // 返回原先记录的next节点
29         return e;
30     }
31     // 前一个节点
32     final Entry<K,V> prevEntry() {
33         Entry<K,V> e = next;
34         if (e == null)
35             throw new NoSuchElementException();
36         if (modCount != expectedModCount)
37             throw new ConcurrentModificationException();
38         // 获取指定节点的“前任”(按遍历次序的前一个节点)
39         next = predecessor(e);
40         // 记录被返回的节点
41         lastReturned = e;
42         return e;
43     }
44     // 移除最近一次被返回的节点
45     public void remove() {
46         if (lastReturned == null)
47             throw new IllegalStateException();
48         if (modCount != expectedModCount)
49             throw new ConcurrentModificationException();
50         // deleted entries are replaced by their successors
51         if (lastReturned.left != null && lastReturned.right != null)
52             /* 如果被删除节点有两个孩子,删除节点e的时候e的引用会被修改为指向原节点的继承者,所以这里先保留next对lastReturned的引用,这样在删除节点后就能获取到继承者的引用,继而继续遍历树 */
53             next = lastReturned;
54         // 删除节点
55         deleteEntry(lastReturned);
56         expectedModCount = modCount;
57         lastReturned = null;
58     }
59 }
复制代码

     PrivateEntryIterator类的prevEntry()方法用到了predecessor(Entry<K,V> t)方法,下面对这个方法进行介绍。

     predecessor(Entry<K,V> t)方法返回传入节点的“前一个”节点,至于前一个节点是哪个节点,这和树的遍历次序相关。根据successor(Entry<K,V> t)和predecessor(Entr

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值