基于TreeMap的NavigableSet实现。使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator进行排序,具体取决于使用的构造方法。
此实现为基本操作(add、remove和contains)提供受保证的log(n)时间开销。
注意,如果要正确实现Set接口,则set维护的顺序(无论是否提供了显式比较器)必须与equals一致。(关于与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是按照equals操作定义的,但TreeSet实例使用它的compareTo(或compare)方法对所有元素进行比较,因此从set的观点来看,此方法认为相等的两个元素就是相等的。即使set的顺序与equals不一致,其行为也是定义良好的;它只是违背了Set接口的常规协定。
注意,此实现不是同步的。如果多个线程同时访问一个TreeSet,而其中至少一个线程修改了该set,那么它必须外部同步。这一般是通过对自然封装该set的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用Collections.synchronizedSortedSet方法来“包装”该set。此操作最好在创建时进行,以防止对set的意外非同步访问: SortedSet s= Collections.synchronizedSortedSet(new TreeSet(…));
此类的iterator方法返回的迭代器是fail-fast的:在创建迭代器之后,如果从结构上对set进行修改(除非通过迭代器自身的remove方法),否则在其他任何时间以任何方式进行修改都将导致迭代器抛出ConcurrentModificationException。因此,对于并发的修改,迭代器很快就完全失败,而不会冒着在将来不确定的时间发生不确定行为的风险。
注意,迭代器的fail-fast行为无法得到保证,一般来说,存在不同步的并发修改时,不可能作出任何肯定的保证。fail-fast迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测bug。
此类是Java Collections Framework的成员。
@author Josh Bloch @see Collection @see Set @see HashSet @see Comparable @see Comparator @see TreeMap @since 1.2
TreeSet与Collection关系如下图:
域
/** * The backing map. */ private transient NavigableMap<E,Object> m; /** * 前面讲了,TreeSet是依赖于TreeMap的,底层就是一个TreeMap实例。TreeMap是保存键值对的,但我们保存TreeSet的时候肯定只是想保存key,那么调用hashMap(key,value)时value应该传什么值呢?PRESENT就是要传value。 */ private static final Object PRESENT = new Object();构造方法
TreeSet(NavigableMap<E,Object> m):根据指定的NavigableMap构造一个set。 TreeSet():构造一个新的空set,该set根据其元素的自然顺序进行排序。 TreeSet(Comparator<? super E> comparator):构造一个新的空TreeSet,它根据指定比较器进行排序。 TreeSet(Collection<? extends E> c):构造一个包含指定collection元素的新TreeSet,它按照其元素的自然顺序进行排序。 TreeSet(SortedSet<E> s):构造一个与指定有序set具有相同映射关系和相同排序的新TreeSet。总结:
(01) TreeSet实际上是TreeMap实现的。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。 (02) TreeSet是非线程安全的。 (03) TreeSet实现java.io.Serializable的方式。当写入到输出流时,依次写入“比较器、容量、全部元素”;当读出输入流时,再依次读取。