一、官方介绍
- 基于TreeMap的NavigableSet实现。元素使用它们的自然顺序排序,或者通过在设置创建时提供的比较器进行排序,这取决于使用的是哪个构造函数。
- 这个实现为基本操作(添加、删除和包含)提供了保证的log(n)时间开销。
- 请注意,如果要正确实现set接口,set维护的顺序(不管是否提供显式comparator)必须与equals一致。(参见Comparable或Comparator获得与equals一致的精确定义。)这是因为Set接口是根据equals操作定义的,但是TreeSet实例使用它的compareTo(或compare)方法执行所有的元素比较,根据该方法判断两个元素是否相等。从Set的角度来看,equal。一个Set的行为是定义良好的,即使它的顺序与equals不一致;只是没有遵守Set接口的一般约定。(此段翻译很有争议,恳请指正)
- 注意,这个实现不是同步的。如果多个线程同时访问tree set,并且至少有一个线程修改tree set,则必须在外部对tree set进行同步。这通常是通过对一些自然封装了集合的对象进行同步来实现的。如果不存在这样的对象,则应该使用集合来“包装”集合。Collections.synchronizedSortedSet方法。这最好在创建时完成,以防止意外的不同步访问Set:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
- 这个类的iterator和listIterator方法返回的迭代器是 fail-fast的:如果在创建迭代器之后的任何时候,以任何方式(除了通过迭代器自己的删除或添加方法)对列表进行结构修改,迭代器将抛出ConcurrentModificationException异常。因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在将来某个不确定的时间冒任意的、不确定的行为的风险。
- 注意,不能保证迭代器的快速故障行为,因为通常来说,在存在非同步并发修改的情况下,不可能做出任何严格的保证。Fail-fast迭代器在最大努力的基础上抛出ConcurrentModificationException。因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的 fail-fast 行为应该只用于检测bug。
- 该类是Java集合框架的成员
二、源码分析
大部分方法都是对TreeMap的方法的封装,详细分析还是放在treeMap吧
package java.util;
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
{
/**
* 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();
/**
* Constructs a set backed by the specified navigable map.
*/
TreeSet(NavigableMap<E, Object> m)
{
this.m = m;
}
/**
* 构造一个新的nullTreeMap,根据其元素的自然顺序排序。所有插入到集合中的元素必须实现可比接口。此外,所有这些元素都必须相互可比
*/
public TreeSet()
{
this(new TreeMap<E, Object>());
}
/**
* 构造一个新的nullTreeMap,根据指定的比较器排序。所有元素插入到集合必须由指定比较器相互可比
*
* @param comparator
*/
public TreeSet(Comparator<? super E> comparator)
{
this(new TreeMap<>(comparator));
}
/**
* 构造一个新的nullTreeMap,根据其元素的自然顺序排序。所有插入到集合中的元素必须实现可比接口。此外,所有这些元素都必须相互可比
*
* @param c
*/
public TreeSet(Collection<? extends E> c)
{
this();
addAll(c);
}
/**
* 构造一个包含相同元素的TreeMap,并使用与指定的已排序集相同的顺序。
*
* @param s
*/
public TreeSet(SortedSet<E> s)
{
this(s.comparator());
addAll(s);
}
/**
* 以升序返回此集合中元素的迭代器.
*
* @return an iterator over the elements in this set in ascending order
*/
public Iterator<E> iterator()
{
return m.navigableKeySet().iterator();
}
/**
* 按降序返回该集合中元素的迭代器。
*
* @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());
}
/**
* Returns the number of elements in this set (its cardinality).
*
* @return the number of elements in this set (its cardinality)
*/
public int size()
{
return m.size();
}
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
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;
}
public void clear()
{
m.clear();
}
public boolean addAll(Collection<? extends E> c)
{
// 如果符合,使用线性时间版本 具体介绍见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);
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;
}