TreeSet
底层为TreeMap
,故本文主要围绕TreeMap
展开
TreeSet简述
核心成员变量
private transient NavigableMap<E,Object> m;
,用于存储TreeMap
对象
TreeSet
与TreeMap
均实现了NavigableSet
接口。
对该接口感兴趣的可见下文
https://blog.csdn.net/kubiderenya/article/details/105303505
构造器
TreeSet(NavigableMap<E,Object> m)
TreeSet()
,调用构造器1TreeSet(Comparator<? super E> comparator)
,调用构造器1TreeSet(Collection<? extends E> c)
,调用构造器2与addAll
方法TreeSet(SortedSet<E> s)
,调用构造器3与addAll
方法
上述方法本质都是调用map
的构造器实现
成员方法
核心方法基本上都是调用成员变量的m
的方法实现。
TreeMap
核心成员变量
private final Comparator<? super K> comparator;
,比较器private transient Entry<K,V> root;
,底层虽然是红黑树,但可以简单理解成二叉排序树的根
构造器
TreeMap()
TreeMap(Comparator<? super K> comparator)
TreeMap(Map<? extends K, ? extends V> m)
TreeMap(SortedMap<K, ? extends V> m)
内容简单明了,不作赘述
成员方法
put(K key, V value)
细节:- 利用
compare(Object k1, Object k2)
方法对key
进行类型检查和null判断 TreeMap
维护的是一颗类二叉排序树。比较器比较后,若插入值小于当前值则左插,反之不然。Comparable<? super K> k = (Comparable<? super K>) key;
,由于该语句并为检查key是否实现了Comparable
接口,因此此处可能会抛出类型异常。
- 利用
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
//偷懒,实际是借助该方法保证key非null且为Object子类
//笔者认为,不如把此处检查放到最开头。key的类型检查和根是否为null没有逻辑关系
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
//比较后若小于当前值,则左插,否则右插
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
//cmp不为0则t必然指向null,即结点还未插入
if (cmp < 0)
parent.left = e;
else
parent.right = e;
//红黑树平衡结点的方法
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
增删改查相关方法,如remove
、get
,功能逻辑都比较简单。
TreeMap
的大部分源码都聚焦于树方法(默认是中序遍历,基于此就有了头结点查找、尾结点查找、前驱查找、后续查找等等)及红黑树平衡上。
这里先留个坑。