从图中可以看出:
(01) TreeSet继承于AbstractSet,并且实现了NavigableSet接口。
(02) TreeSet的本质是一个"有序的,并且没有重复元素"的集合,它是通过TreeMap实现的。TreeSet中含有一个"NavigableMap类型的成员变量"m,而m实际上是"TreeMap的实例"。
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
// 使用NavigableMap的key来保存Set集合的元素
private transient NavigableMap<E,Object> m;
// 使用一个PRESENT作为Map集合的所有value
private static final Object PRESENT = new Object();
// 包访问权限的构造器,以指定的NavigableMap对象创建Set集合
TreeSet(NavigableMap<E,Object> m) {
this.m = m;马士兵
}
public TreeSet() { // ①
// 以自然顺序方式创建一个新的TreeMap,根据该TreeSet创建一个TreeSet
this(new TreeMap<E,Object>());
}
public TreeSet(Comparator<? super E> comparator) { // ②
// 以定制顺序方式创建一个新的TreeMap,根据该TreeSet创建一个TreeSet
// 使用该TreeMap的key来保存Set集合的元素
this(new TreeMap<E,Object>(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);
}
public boolean addAll(Collection<? extends E> c) {
// Use linear-time version if applicable
if (m.size()==0 && c.size() > 0 &&
c instanceof SortedSet &&
m instanceof TreeMap) {
// 把c集合强制转换为SortedSet集合
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
// 把m集合强制转换为TreeMap集合
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
Comparator<? super E> mc = map.comparator();
// 如果cc和mc两个Comparator相等
if (cc==mc || (cc != null && cc.equals(mc))) {
// 把Collection中所有元素添加成TreeMap集合的key
map.addAllForTreeSet(set, PRESENT);
return true;
}
}
// 直接调用父类的addAll()方法来实现
return super.addAll(c);
}
}
与HashSet完全类似的是,TreeSet里绝大部分方法都是直接调用TreeMap的方法来实现的。
TreeSet中的重要方法
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
public void clear() {
m.clear();
}
public boolean contains(Object o) {
return m.containsKey(o);
}
public E first() {
return m.firstKey();
}
public E last() {
return m.lastKey();
}
可以看到TreeSet中与TreeMap中同名的方法全部都是调用的TreeMap中的方法来实现的,其中add方法在调用TreeMap的put方法时第二个参数传入的是固定值PRESENT,一个Object类型对象。
总结
1TreeSet底层是基于TreeMap的(而TreeMap是基于红黑树的),但是仅仅用来保存Key,而不保存Value,因为TreeSet的add()方法在调用TreeMap的put方法的时候第二个参数传入的都是PRESENT这个固定的Object对象。
2可以看到TreeSet中的add与remove等方法均无synchronized关键字修饰,即TreeSet不是线程安全的,如果要使用同步的TreeSet需要使用Collections集合类的静态方法,即Set s=Collections.synchronizedSet(new TreeSet());
3TreeSet中的元素是自动排好序的,插入的值不允许为null。
4TreeSet中元素的值必须是唯一的,因为TreeSet底层是基于TreeMap的,而TreeMap不允许元素key重复。