说明
基于 TreeMap 的 NavigableSet实现。元素使用它们的Comparable 自然排序 排序,或者通过在集合创建时提供的 Comparator 排序,具体取决于使用的构造函数。
此实现为基本操作( add、 remove 和 contains)提供有保证的 log(n) 时间成本。
请注意,如果要正确实现 Set 接口,则集合维护的排序(无论是否提供显式比较器)必须与 equals 一致。 (请参阅 Comparable 或 Comparator 以获得 consistent with equals 的精确定义。)之所以如此,是因为 Set 接口是根据 equals 操作,但 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,因此从集合的角度来看,此方法认为相等的两个元素是,相等。集合 的行为是明确定义的,即使它的顺序与 equals 不一致;它只是不遵守 Set 接口的一般约定。
注意这个实现不是同步的。如果多个线程同时访问一个树集,并且至少有一个线程修改了这个集,它必须在外部同步。这通常是通过同步一些自然封装集合的对象来实现的。如果不存在此类对象,则应使用 CollectionssynchronizedSortedSet Collections.synchronizedSortedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
这个类的 返回的迭代器code iterator 方法是fail-fast:如果在迭代器创建后的任何时间修改集合,除了通过迭代器自己的 remove 方法外,迭代器将抛出一个 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬性保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。 # 源码分析
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* 通过一个NavigableMap来构造一个TreeSet。
*/
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
/**
* 构造一个新的空树集,根据其元素的自然顺序进行排序。插入到集合中的所有元素都必须实现 { Comparable} 接口
*/
public TreeSet() {
this(new TreeMap<E,Object>());
}
/**
* 构造一个新的空树集,根据指定的比较器进行排序。插入集合的所有元素必须通过指定的比较器<i>相互比较<i>:{@code comparer.compare(e1, e2)} 不得为任何元素抛出 {@code ClassCastException} {@code e1}和 {@code e2} 在集合中。如果用户尝试向集合中添加违反此约束的元素,{@code add} 调用将抛出 {@code ClassCastException}。
*/
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
/**
* 构造一个包含指定集合中元素的新树集,根据其元素的<i>自然顺序<i>排序。插入到集合中的所有元素都必须实现 {@link Comparable} 接口。此外,所有这些元素必须<i>相互比较<i>:{@code e1.compareTo(e2)} 不得为任何元素 {@code e1} 和 {@code e2} 抛出 {@code ClassCastException}集。
*/
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* 构造一个包含相同元素并使用与指定排序集相同的顺序的新树集。
*/
public TreeSet(SortedSet<E> s) {
this(s.comparator());
addAll(s);
}
/**
*迭代器
*/
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
/**
* Returns an iterator over the elements in this set in descending order.
*
* @return an iterator over the elements in this set in descending order
* @since 1.6
*/
public Iterator<E> descendingIterator() {
return m.descendingKeySet().iterator();
}
/**
* @since 1.6
*/
public NavigableSet<E> descendingSet() {
return new TreeSet<>(m.descendingMap());
}
/**
* set的元素数量
*/
public int size() {
return m.size();
}
/**
* 是否为空
*/
public boolean isEmpty() {
return m.isEmpty();
}
/*
*/
public boolean contains(Object o) {
return m.containsKey(o);
}
/**
* 添加元素
*/
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
/**
* 移除元素
*/
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
/**
* 清空set
*/
public void clear() {
m.clear();
}
/**
* 添加该集合中的所有元素
*/
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) {
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);
return true;
}
}
return super.addAll(c);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code fromElement} or {@code toElement}
* is null and this set uses natural ordering, or its comparator
* does not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
* @since 1.6
*/
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive) {
return new TreeSet<>(m.subMap(fromElement, fromInclusive,
toElement, toInclusive));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code toElement} is null and
* this set uses natural ordering, or its comparator does
* not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
* @since 1.6
*/
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
return new TreeSet<>(m.headMap(toElement, inclusive));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code fromElement} is null and
* this set uses natural ordering, or its comparator does
* not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
* @since 1.6
*/
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
return new TreeSet<>(m.tailMap(fromElement, inclusive));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code fromElement} or
* {@code toElement} is null and this set uses natural ordering,
* or its comparator does not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
*/
public SortedSet<E> subSet(E fromElement, E toElement) {
return subSet(fromElement, true, toElement, false);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code toElement} is null
* and this set uses natural ordering, or its comparator does
* not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
*/
public SortedSet<E> headSet(E toElement) {
return headSet(toElement, false);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if {@code fromElement} is null
* and this set uses natural ordering, or its comparator does
* not permit null elements
* @throws IllegalArgumentException {@inheritDoc}
*/
public SortedSet<E> tailSet(E fromElement) {
return tailSet(fromElement, true);
}
public Comparator<? super E> comparator() {
return m.comparator();
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E first() {
return m.firstKey();
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E last() {
return m.lastKey();
}
// NavigableSet API methods
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified element is null
* and this set uses natural ordering, or its comparator
* does not permit null elements
* @since 1.6
*/
public E lower(E e) {
return m.lowerKey(e);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified element is null
* and this set uses natural ordering, or its comparator
* does not permit null elements
* @since 1.6
*/
public E floor(E e) {
return m.floorKey(e);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified element is null
* and this set uses natural ordering, or its comparator
* does not permit null elements
* @since 1.6
*/
public E ceiling(E e) {
return m.ceilingKey(e);
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified element is null
* and this set uses natural ordering, or its comparator
* does not permit null elements
* @since 1.6
*/
public E higher(E e) {
return m.higherKey(e);
}
/**
* @since 1.6
*/
public E pollFirst() {
Map.Entry<E,?> e = m.pollFirstEntry();
return (e == null) ? null : e.getKey();
}
/**
* @since 1.6
*/
public E pollLast() {
Map.Entry<E,?> e = m.pollLastEntry();
return (e == null) ? null : e.getKey();
}
/**
* Returns a shallow copy of this {@code TreeSet} instance. (The elements
* themselves are not cloned.)
*
* @return a shallow copy of this set
*/
@SuppressWarnings("unchecked")
public Object clone() {
TreeSet<E> clone;
try {
clone = (TreeSet<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
clone.m = new TreeMap<>(m);
return clone;
}
/**
* Save the state of the {@code TreeSet} instance to a stream (that is,
* serialize it).
*
* @serialData Emits the comparator used to order this set, or
* {@code null} if it obeys its elements' natural ordering
* (Object), followed by the size of the set (the number of
* elements it contains) (int), followed by all of its
* elements (each an Object) in order (as determined by the
* set's Comparator, or by the elements' natural ordering if
* the set has no Comparator).
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden stuff
s.defaultWriteObject();
// Write out Comparator
s.writeObject(m.comparator());
// Write out size
s.writeInt(m.size());
// Write out all elements in the proper order.
for (E e : m.keySet())
s.writeObject(e);
}
/**
* Reconstitute the {@code TreeSet} instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden stuff
s.defaultReadObject();
// Read in Comparator
@SuppressWarnings("unchecked")
Comparator<? super E> c = (Comparator<? super E>) s.readObject();
// Create backing TreeMap
TreeMap<E,Object> tm = new TreeMap<>(c);
m = tm;
// Read in size
int size = s.readInt();
tm.readTreeSet(size, s, PRESENT);
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* set.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
* {@link Spliterator#DISTINCT}, {@link Spliterator#SORTED}, and
* {@link Spliterator#ORDERED}. Overriding implementations should document
* the reporting of additional characteristic values.
*
* <p>The spliterator's comparator (see
* {@link java.util.Spliterator#getComparator()}) is {@code null} if
* the tree set's comparator (see {@link #comparator()}) is {@code null}.
* Otherwise, the spliterator's comparator is the same as or imposes the
* same total ordering as the tree set's comparator.
*
* @return a {@code Spliterator} over the elements in this set
* @since 1.8
*/
public Spliterator<E> spliterator() {
return TreeMap.keySpliteratorFor(m);
}
private static final long serialVersionUID = -2479143000061671589L;
}
总结
(1)TreeSet实际上是TreeMap实现的。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。
(02) TreeSet是非线程安全的。
(03) TreeSet实现java.io.Serializable的方式。当写入到输出流时,依次写入“比较器、容量、全部元素”;当读出输入流时,再依次读取。