Collection容器家族(TreeSet源码详解)
一、在Collection集合体系中的位置及概述
TreeSet继承自AbstractSet抽象类,实现了NavigableSet、Serializable、Cloneable、RandomAccess接口。它的特点是存储元素唯一,无序(输入和输出无序)。 TreeSet默认情况下是基于TreeMap实现的,是对TreeMap的封装。默认情况下和TreeMap一样,采用元素的内部比较器Comparable的compareTo方法来比较元素的大小。如果不用内部比较器,就需要在外部传入一个Comparator的实现类来比较。由于TreeMap实现中采用红黑树实现,所以add,remove,contains方法的时间复杂度最坏情况下能保证log( n )。
二、成员变量
// 存放元素的Map,必须是实现了NavigableMap接口的类
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
// 一个虚拟值,用于添加元素到map中时,key为元素的值,value用此虚拟值代替
private static final Object PRESENT = new Object();
三、构造方法
// 自定义实现了NavigableMap接口的Map来作为实现
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
// 默认构造方法用TreeMap来实现
public TreeSet() {
this(new TreeMap<E,Object>());
}
// 以定制排序方式创建一个新的 TreeMap,
// 根据该 TreeSet 创建一个 TreeSet,
// 使用该 TreeMap 的 key 来保存 Set 集合的元素
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
//使用参数集合的元素构造本集合
public TreeSet(Collection<? extends E> c) {
// 无参构造器创建一个TreeSet,底层以TreeMap保存集合元素
this();
// 向TreeSet中添加Collection集合c里的所有元素
addAll(c);
}
public TreeSet(SortedSet<E> s) {
// 调用带比较器参数的构造器创建衣蛾TreeSet,底层以TreeMap保存集合元素
this(s.comparator());
// 向TreeSet中添加SortedSet集合s里的所有元素
addAll(s);
}
其中涉及到addAll方法:
// 将参数集合中所有元素添加到本集合中
public boolean addAll(Collection<? extends E> c) {
// Use linear-time version if applicable
// 条件:本集合为空、参数集合有元素、参数集合是SortedSet类型、m是TreeMap类型
if (m.size()==0 && c.size() > 0 &&
c instanceof SortedSet &&
m instanceof TreeMap) {
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
Comparator<?> cc = set.comparator(); // 获取比较器
Comparator<? super E> mc = map.comparator(); // 获取比较器
if (cc==mc || (cc != null && cc.equals(mc))) { // 如果本集合比较器和参数集合比较器相同
map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法将参数集合所有元素添加到本集合
return true;
}
}
return super.addAll(c); // 不满足上诉条件,则调用AbstractCollection超类的addAll方法添加
}
其中涉及到TreeMap的addAllForTreeSet方法,查看我之前的博客。
四、常用API
1.添加元素
// 添加元素
public boolean add(E e) {
// 调用TreeMap的put方法添加
return m.put(e, PRESENT)==null;
}
// 将参数集合中所有元素添加到本集合中
public boolean addAll(Collection<? extends E> c) {
// Use linear-time version if applicable
// 条件:本集合为空、参数集合有元素、参数集合是SortedSet类型、m是TreeMap类型
if (m.size()==0 && c.size() > 0 &&
c instanceof SortedSet &&
m instanceof TreeMap) {
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
Comparator<?> cc = set.comparator(); // 获取比较器
Comparator<? super E> mc = map.comparator(); // 获取比较器
if (cc==mc || (cc != null && cc.equals(mc))) { // 如果本集合比较器和参数集合比较器相同
map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法将参数集合所有元素添加到本集合
return true;
}
}
return super.addAll(c); // 不满足上诉条件,则调用AbstractCollection超类的addAll方法添加
}
2.删除元素
// 清空集合所有元素
public void clear() {
// 调用TreeMap方法清除
m.clear();
}
// 移除参数元素
public boolean remove(Object o) {
// 调用TreeMap方法清除
return m.remove(o)==PRESENT;
}
3.遍历操作
public Iterator<E> iterator() {
// 调用TreeMap方法清除
return m.navigableKeySet().iterator();
}
五、总结
TreeSet原码中方法比较少,原因是因为他是TreeMap的封装类对象。提的的就不在此赘述了。