Java 数据结构 -- 13.Java 8 数据结构 TreeSet

前言

书接上文,上一篇中对 Set 接口最终实现类 HashSet 与 LinkedHashSet 做了介绍与分析,本篇将对另一种 Set 接口的最终实现类 TreeSet 进行介绍与分析。

先来看下 TreeSet 完整的继承结构图
Java 数据结构 -- 13.Java 8 数据结构 TreeSet_第1张图片

可以看到 TreeSet 与 HastSet 不同,不仅继承自 AbstarctSet 类,还实现了 SortSet 与它的子类 NavigableSet 接口,所以在查看 TreeSet 的源码之前,必须先来看一下 SortedSet 与 NavigableSet 接口。

/**
 * 一个进一步提供它的所有元素整个顺序的 Set。
 * 元素由它们的自然 Comparable 排序,或者通过一个由顺序 set 创建时特别提供的 
 * Comparator。这个 set 的迭代器将会以递增元素顺序横穿 set。提供多个额外的操作来支持排
 * 序。(这个接口与 SortedMap 的 set 类似。)
 *
 * 所有加入一个有序的 set 的元素必须实现 Comparable 接口(或者接收一个特定的 
 * comparator)。进一步说,这样的元素必须是彼此可以比较的:e1.compareTo(e2) (或者 
 * comparator.compare(e1, e2)) 必须对于顺序 set 中的任何元素 e1 和 e2 不抛出一个 
 * ClassCastException。 试图违反这个规约将导致侵犯方法或者调用构造器来抛出一个 
 * ClassCastException。
 * 
 * 注意,如果有序 set 要正确实现 Set 接口的话,由一个有序 set(不管是不是明确提供了 
 * comparator) 维护的顺序必须与 equals 方法等价。(查看 Comparable 接口或者 
 * Comparator 了解来了解与 equals 等价的明确定义。)必须这样的原因是 Set 接口是根据 
 * equals 操作定义的,但是一个有序 set 通过使用元素的 compareTo 或者 compare 方法比
 * 对所有元素来完成它的表现,所以通过这个方法被认为相同的两个元素从有序 set 的立场,是 
 * equal。这种有序 set 的行为是被完好定义的,即是它的顺序是与 equals 等价的;它只是
 * 没有遵守 Set 接口的通用约定。
 * 
 * 所有通用目的的有序 set 实现类应该提供 4 个“标准”的构造器:1)一个空的(没有参数)构造
 * 的,构建一个空的对它的元素自然排序的有序 set。2)一个接收一个 Comparator 类参数的构
 * 造器,构建一个空的根指定 comparator 排序的有序 set。3)一个接收一个 Collection 类
 * 参数的构造器,构建一个包含参数重同样元素的新的有序 set,根据元素的自然顺序排序。4)一
 * 个接收一个 SortedSet 类型参数的构造器,构建一个新的包含了与输入有序 set 相同元素与顺
 * 序的有序 set。没有方法能强制执行这种推荐方法,因为接口不能包含构造器。
 * 
 * 注意:多个方法返回有限范围的对象。比如范围是 half-open,它的意思是,它们包含它们的低
 * 端点而不是他们的高端点(适当的。)如果你需要一个 closed range(包含两个端点),并且元
 * 素类型允许是一个给定值的中继器计算后的结果,只要请求从低端点到中继器(高端点)的子范
 * 围。例如,假设 s 是一个 strings 的有序 set。下列惯用语义包含一个包含了所有 s 中从 
 * low 到 high 的视图,包括:
 *   SortedSet sub = s.subSet(low, high+"\0");
* * 一个类似的技术可以用来生成一个开放区间(两个端点都不包含)。下列惯用语义包含了一个所有 * s 中从 low 到 high 的视图,包括:
 *   SortedSet sub = s.subSet(low+"\0", high);
* * SortedSet 接口,继承自 Set 接口 */
public interface SortedSet<E> extends Set<E> { /** * 返回用来为 set 中元素排序的 comparator,或者返回 null,如果这个 set 使用 * (Comparable 自然排序)它的元素的话 */ Comparator<? super E> comparator(); /** * 返回一个这个 set 的部分包含范围从 fromElement(闭区间)到 toElement(开区间) * 的视图。(如果 fromElement 与 toElement 相等,返回的 set 为空。)返回的 set * 是由当前 set 支持的,所以对于返回的 set 的修改也会影响到当前到 set,反之亦然。 * 这个返回 set 支持这个 set 支持的所有可选的 set 操作。 * * 试图向返回的 set 的范围之外添加一个元素将将会抛出一个 * IllegalArgumentException。 */ SortedSet<E> subSet(E fromElement, E toElement); /** * 返回一个这个 set 的部分严格小于 toElement 的视图。(如果 fromElement 与 * toElement 相等,返回的 set 为空。)返回的 set 是由当前 set 支持的,所以对于返 * 回的 set 的修改也会影响到当前到 set,反之亦然。这个返回 set 支持这个 set 支持 * 的所有可选的 set 操作。 * * 试图向返回的 set 的范围之外添加一个元素将将会抛出一个 * IllegalArgumentException。 */ SortedSet<E> headSet(E toElement); /** * 返回一个这个 set 的部分大于等于 fromElement 的视图。(如果 fromElement 与 * toElement 相等,返回的 set 为空。)返回的 set 是由当前 set 支持的,所以对于返 * 回的 set 的修改也会影响到当前到 set,反之亦然。这个返回 set 支持这个 set 支持 * 的所有可选的 set 操作。 * * 试图向返回的 set 的范围之外添加一个元素将将会抛出一个 * IllegalArgumentException。 */ SortedSet<E> tailSet(E fromElement); /** * 返回当前 set 中第一个(最低位)元素,set 为空时候抛出 NoSuchElementException */ E first(); /** * 返回当前 set 中最后一个(最高位)元素,set 为空时候抛出 NoSuchElementException */ E last(); /** * 构造一个包含当前有序 set 中所有元素的并行迭代器 * Creates a {@code Spliterator} over the elements in this sorted set. * * 并行迭代器携带 DISTINCT,SORTED,ORDERED 特征值。实现类因该记录其他额外的特征 * 值。 * * 如果有序 set 的 comparator (查看 {@link #comparator()} 是 null),那么并 * 行迭代器的 comparator(查看 {@link * java.util.Spliterator#getComparator()})必须是 null。 * 不然的话,并行迭代器的 comparator 必须与有序 set 的 comparator 完全相同。 */ @Override default Spliterator<E> spliterator() { return new Spliterators.IteratorSpliterator<E>( this, Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED) { @Override public Comparator<? super E> getComparator() { return SortedSet.this.comparator(); } }; } }

根据 SortedSet 的源码可以看到,SortedSet 定义了一些因为有序特性而可以支持的方法,有序特性是通过 comparable/comparator 和 equals 方法实现的,另外要求有序的实现必须与 equals 等价(这里可以通过一个例子了解,如果是通过 userId 来实现等价的,那么也应该基于 userId 来进行比较,而不是基于 userName)。

接下来看下 NavigableSet 的源码

/**
 * 一个扩展了报道与给定查询目标最近符合导航方法的 {@link SortedSet}。方法 {@code lower},
 * {@code floor}, {@code ceiling}, 和 {@code higher} 返回元素分别小于,小于等于,大于等于和大于一个
 * 给定元素,如果没有这样的元素则返回 {@code null}。一个 {@code NavigableSet} 可能从正向或反向被访问和
 * 贯穿。{@code descendingSet} 方法返回一个所有相关的和有向方法的倒置 set 视图。正向操作和视图的性能要比
 * 方向的更好。这个接口额外定义了返回并移除最低位和最高位元素的方法 {@code pollFirst} 和 {@code 
 * pollLast},如果不存在,在返回 {@code null}。方法 @code subSet}, {@code headSet} 和 {@code 
 * tailSet} 与 {@code SortedSet} 类似名称方法不同之处在于接收额外的描述最低或者最高绑定参数是必须见还是
 * 开区间。任何 {@code NavigableSet} 的子 sets 必须实现 {@code NavigableSet} 接口。
 *
 * 导航方法的返回值可能在允许 {@code null} 元素的实现类中是有歧义的。但是,就算是这种情况结果也能通过 
 * {@code contains(null)} 来消除这种歧义。为了避免这种问题,这个接口的实现类被鼓励不要插入 {@code null} 
 * 元素。(注意 {@link Comparable} 元素的有序 sets 本身就不允许 {@code null} 。)
 * 
 * 方法 
 * {@link #subSet(Object, Object) subSet(E, E)},
 * {@link #headSet(Object) headSet(E)}, and
 * {@link #tailSet(Object) tailSet(E)}
 * 是特意返回 {@code SortedSet} 来允许存在的 {@code SortedSet} 实现类成为实现 {@code NavigableSet} 
 * 接口的相容重构类,但是这个接口的扩展和实现被鼓励为通过返回 {@code NavigableSet} 来重写这些方法。
 */
public interface NavigableSet<E> extends SortedSet<E> {
  
    /**
     * 返回这个 set 中严格小于给定元素的最高位元素,或者如果没有这种元素的话返回 {@code null}
     */
    E lower(E e);

    /**
     * 返回这个 set 中小于等于给定元素的最高位元素,或者如果没有这种元素的话返回 {@code null}
     */
    E floor(E e);

    /**
     * 返回这个 set 中大于等于给定元素的最低位元素,或者如果没有这种元素的话返回 {@code null}
     */
    E ceiling(E e);

    /**
     * 返回这个 set 中严格大于给定元素的最高位元素,或者如果没有这种元素的话返回 {@code null}
     */
    E higher(E e);

    /**
     * 返回并且移除第一个(最低位)元素,或者如果没有这种元素的话返回 {@code null}
     */
    E pollFirst();

    /**
     * 返回并且移除最后一个(最高位)元素,或者如果没有这种元素的话返回 {@code null}
     */
    E pollLast();

    /**
     * 返回一个包含 set 中所有元素的正向迭代器
     */
    Iterator<E> iterator();

    /**
     * 返回一个包含 set 中所有元素的反向顺序的视图。反向 set 是被当前 set 支持的,所以对于 set 的修改也会
     * 影响到反向 set,反之亦然。如果任何一个 set 在迭代操作过程中被修改了(除了通过迭代器自己的 {@code 
     * remove} 操作),迭代操作的返回时不可定义的
     * 
     * 返回 set 有一个与 
     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())
     * 相等性的顺序
     *
     * {@code s.descendingSet().descendingSet()} 表达式返回与 {@code s} 相等。
     */
    NavigableSet<E> descendingSet();

    /**
     * 返回一个包含 set 中所有元素的反向迭代器。与 {@code descendingSet().iterator()} 相等
     */
    Iterator<E> descendingIterator();

    /**
     * 返回当前 set 的一部分范围从 {@code fromElement} 到 {@code toElement} 的视图。如果 {@code 
     * fromElement} 与 {@code toElement} 相等,返回的 set 是空的除非 {@code fromInclusive} 和 
     * {@code toInclusive} 都为 true。返回的 set 由当前 set 支持,所以修改返回的 set 会影响到当前 
     * set,反之亦然。返回 set 支持所有当前 set 支持的可选 set 操作。
     *
     * 试图向范围外添加一个元素的操作会抛出 {@code IllegalArgumentException}
     */
    NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                           E toElement,   boolean toInclusive);

    /**
     * 返回当前 set 的一部分小于(或者等于,如果 {@code inclusive} 是 true 的话){@code toElement} 
     * 的视图。返回的 set 由当前 set 支持,所以修改返回的 set 会影响到当前 set,反之亦然。返回 set 支持
     * 所有当前 set 支持的可选 set 操作。
     *
     * 试图向范围外添加一个元素的操作会抛出 {@code IllegalArgumentException}。
     */
    NavigableSet<E> headSet(E toElement, boolean inclusive);

    /**
     * 返回当前 set 的一步大于(或者等于,如果 {@code inclusive} 是 true 的话) {@code fromElement}
     * 的视图。返回的 set 由当前 set 支持,所以修改返回的 set 会影响到当前 set,反之亦然。返回 set 支持
     * 所有当前 set 支持的可选 set 操作。
     *
     * 试图向范围外添加一个元素的操作会抛出 {@code IllegalArgumentException}。
     */
    NavigableSet<E> tailSet(E fromElement, boolean inclusive);

    /**
     * 与 {@code subSet(fromElement, true, toElement, false)} 方法相同
     */
    SortedSet<E> subSet(E fromElement, E toElement);

    /**
     * 与 {@code headSet(toElement, false)} 方法相同
     */
    SortedSet<E> headSet(E toElement);

    /**
     * 与 {@code tailSet(fromElement, true)} 方法相同
     */
    SortedSet<E> tailSet(E fromElement);
}

根据 NavigableSet 的源码可以看到,NavigableSet 基于 SortedSet 的基础上又提供了一下双向操作,这看上去有点像 LinkedList 的双向链表操作,但是注意不同的是 LinkedList 可以通过下标直接访问元素,这得益于 List 接口赋予的可随机操作特性,但是 NavigableSet 没有这样的特性,它只能基于一个/两个元素提供的范围(根据它们的 comparable/comparator 和 equals 实现)返回一个范围内的元素集合。

接下来就可以看 TreeSet 的源码了。

/**
 * 一个基于 {@link TreeMap} 的 {@link NavigableSet} 实现类。元素使用它们的 Comparable 自然排序,或者
 * 通过一个在建立 set 的时候提供的 {@link Comparator}  来排序的,要看使用的是哪个构造器。
 *
 * 这个实现类对于基础操作 ({@code add}, {@code remove} 和 {@code contains}) 提供了 log(n) 时间耗费
 * 的保证。
 *
 * 注意,如果有序 set 要正确实现 Set 接口的话,由一个有序 set(不管是不是明确提供了 comparator) 维护的顺
 * 序必须与 equals 方法等价。(查看 Comparable 接口或者 Comparator 了解来了解与 equals 等价的明确定
 * 义。)必须这样的原因是 Set 接口是根据 equals 操作定义的,但是一个有序 set 通过使用元素的 compareTo 或
 * 者 compare 方法比对所有元素来完成它的表现,所以通过这个方法被认为相同的两个元素从有序 set 的立场,是 
 * equal。这种有序 set 的行为是被完好定义的,即是它的顺序是与 equals 等价的;它只是没有遵守 Set 接口的通
 * 用约定。
 *
 * 注意这个实现类不是线程安全的。如果多线程同时并行地访问一个链接 hash set,并且至少有一个线程修改了 set,
 * 它必须从外部实现线程安全。这通常是通过对于自然封装这个 set 的对象实现线程安全来完成的。
 *
 * 如果没有这样的对象,set 应该被使用 Collections#synchronizedSet 方法“包装”。这最好在被创建时完成,来
 * 防止意外的对于这个 set 的非线程安全的访问 
 *   SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
* * 通过本类的 iterator 方法返回的迭代器是 fail-fast 的:如果在迭代器创建后的任意时间点 set 被结构性的改变 * 了,只要不是通过迭代器自己的 ListIterator#remove 方法,迭代器将会抛出一个 * ConcurrentModificationException。因此,对于表面上的同步更改操作,迭代器失败的快速和干净,而不是在未来 * 的某个不确定的时间点冒险做一些不确定的行为。 * * 注意一个迭代器的 fail-fast 行为是不能被保证的,通常来说,不可能对出现的非线程安全的同时修改操作做任何硬性 * 的保证。基于最佳性能的基础考虑,Fail-fast 迭代器抛出一个 ConcurrentModificationException。因此,建 * 立在这中异常上写出的程序的正确性将会是不健壮的:迭代器的 fail-fast 行为应当植被用于检查 bugs。 * * TreeSet 继承自 AbstractSet,实现了 NavigableSet 接口,Cloneable 接口和 Serializable 接口 */
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { /** * 提供支持的 NaviableMap */ private transient NavigableMap<E,Object> m; // 与一个支持的 Map 中的对象相关的壳值 private static final Object PRESENT = new Object(); /** * 通过一个提供支持的指定导航 map 对象构造一个 set。 */ TreeSet(NavigableMap<E,Object> m) { this.m = m; //初始化 m } /** * 构造一个根据元素自然顺序排序的新的,空的 tree set。所有插入这个 set 的元素必须实现 Comparable 接 * 口。更进一步说,所有此类元素必须是可以手动比较的: 对于 set 中的任何元素 {@code e1} 和 {@code * e2}, {@code e1.compareTo(e2)} 必须不会抛出一个 ClassCastException。如果用户试图违反这个规约 * (比如,用户试图向元素是 intergers 的 set 中添加一个 string 元素)添加一个元素,{@code add} 调 * 用会抛出一个 ClassCastException。 */ public TreeSet() { this(new TreeMap<E,Object>()); //调用带参构造器,参数为一个 TreeMap } /** * 构造一个新的,空的 tree set,按照指定的 comparator 排序。所有插入这个 set 的元素必须实现 * Comparable 接口。更进一步说,所有此类元素必须是可以手动比较的: 对于 set 中的任何元素 {@code e1} * 和 {@code e2}, {@code e1.compareTo(e2)} 必须不会抛出一个 ClassCastException。如果用户试图 * 违反这个规约(比如,用户试图向元素是 intergers 的 set 中添加一个 string 元素)添加一个元素, * {@code add} 调用会抛出一个 ClassCastException。 */ public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); //调用带参构造器,参数为带有一个 comparator 的 TreeMap } /** * 构造一个包含指定数据结构中所有元素的新的 tree set,按照这些元素的自然顺序排序。所有插入这个 set 的 * 元素必须实现Comparable 接口。更进一步说,所有此类元素必须是可以手动比较的: 对于 set 中的任何元素 * {@code e1} 和 {@code e2}, {@code e1.compareTo(e2)} 必须不会抛出一个 ClassCastException。 * 如果用户试图违反这个规约(比如,用户试图向元素是 intergers 的 set 中添加一个 string 元素)添加一 * 个元素,{@code add} 调用会抛出一个 ClassCastException。 */ public TreeSet(Collection<? extends E> c) { this(); //调用无参构造器 addAll(c); //调用 addAll 方法 } /** * 构造一个与指定有序 set 包含所有元素与相同顺序的新的 tree set。 */ public TreeSet(SortedSet<E> s) { this(s.comparator()); //调用带参构造器,参数为 s 的 comparator addAll(s); //调用 addAll 方法 } /** * 返回一个包含所有元素的正向迭代器。 */ public Iterator<E> iterator() { return m.navigableKeySet().iterator(); //返回 m 调用 navigableKeySet 返回结果的串行迭代器 } /** * 返回一个包含所有元素的反向迭代器。 */ public Iterator<E> descendingIterator() { return m.descendingKeySet().iterator(); //返回 m 调用 descendingKeySet 返回结果的串行迭代器 } /** * @since 1.6 */ public NavigableSet<E> descendingSet() { return new TreeSet<>(m.descendingMap()); //调用带参构造器,参数为 m 调用 descendingMap 返回的结果 } /** * 返回这个 set 的元素个数(它的基数)。 */ public int size() { return m.size(); //返回 m 的长度 } /** * 如果这个 set 中不包含任何元素,返回 {@code true}。 */ public boolean isEmpty() { return m.isEmpty(); //返回 m 是否为空 } /** * 如果当前 set 包含指定元素,则返回 {@code true} 。 * 更正式的说,只有当当前 set 中包含一个类似于 {@code e} * (o==null & e==null : o.equals(e)) * 这样的元素时返回 true */ public boolean contains(Object o) { return m.containsKey(o); //返回 m 的键中是否包含 o } /** * 如果当前 set中尚没有这个元素,则向 set 中加入指定元素。更正式的说,如果当前 set 中不包含类似于 * {@code e2} * (e==null ? e2==null : e.equals(e2)) * 这样的元素时,向 set 中添加指定元素 {@code e}。如果 set 中有已经包含了这种元素,调用会不做任何变更 * 的返回 {@code false} */ public boolean add(E e) { return m.put(e, PRESENT)==null; //调用 m.put 方法,比较结果是否是 null 并返回 } /** * 如果当前 set 中存在指定参数相同的元素,则移除。更正式的说,如果 set 中包含类似于 {@code e} * (o==null ? e==null : o.equals(e)) 这样的元素,则移除。如果 set 中包含元素(或者相等,如果当前 * set 作为调用返回被改变了)就返回 {@code true}。(一旦调用返回后这个 set 将不再包含这个元素) */ public boolean remove(Object o) { return m.remove(o)==PRESENT; //调用 m.remove 方法,比较结果是否是 PRESENT 并返回 } /** * 移除当前 set 中的所有元素。方法调用后 set 将变为空。 */ public void clear() { m.clear(); //调用 m.clear 方法 } /** * 向当前 set 中添加指定数据结构中的所有元素 */ public boolean addAll(Collection<? extends E> c) { //如果是适用的,使用线性时间版本 if (m.size()==0 && c.size() > 0 && //如果 m 的长度为 0 c instanceof SortedSet && //并且 c 是 SortedSet 的实例 m instanceof TreeMap) { //并且 m 是 TreeMap 的实例 SortedSet<? extends E> set = (SortedSet<? extends E>) c; //强转 c 为 SortedSet,缓存给 set TreeMap<E,Object> map = (TreeMap<E, Object>) m; //强转 m 为 TreeMap Comparator<?> cc = set.comparator(); //获取 set 的 comparator,缓存给 cc Comparator<? super E> mc = map.comparator(); //获取 map 的 comparator,缓存给 mc if (cc==mc || (cc != null && cc.equals(mc))) { //判断 cc==mc 是否相等,或者 cc 不为 null 并且 cc.equals(mc) map.addAllForTreeSet(set, PRESENT); //调用 map.addAllForTreeSet 方法 return true; //返回 true } } return super.addAll(c); //调用 super.addAll 方法并返回结果 } /**{@inheritDoc}**/ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new TreeSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); //调用带参构造器,参数为 m.subMap 方法接收 fromElement,fromInclusive,toElement,toInclusive 参数后的返回值 } /**{@inheritDoc}**/ public NavigableSet<E> headSet(E toElement, boolean inclusive) { return new TreeSet<>(m.headMap(toElement, inclusive)); //调用带参构造函数,参数为 m.hashMap 方法接收 toElement,inclusive 参数后的返回值 } /**{@inheritDoc}**/ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { return new TreeSet<>(m.tailMap(fromElement, inclusive)); //调用带参构造器,参数为 m.tailMap 方法接收 fromElement,inclusive 参数后的返回值 } /**{@inheritDoc}**/ public SortedSet<E> subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); //调用 subSet 方法,参数为 fomElement,fromInclusive = true,toElement,toInclusive = false } /**{@inheritDoc}**/ public SortedSet<E> headSet(E toElement) { return headSet(toElement, false); //调用 headSet 方法,参数为 toElement,inclusive = false } /**{@inheritDoc}**/ public SortedSet<E> tailSet(E fromElement) { return tailSet(fromElement, true); //调用 tailSet 方法,参数为 fromElement,inclusive = true } /**获取当前 set 的 comparator**/ public Comparator<? super E> comparator() { return m.comparator(); //返回 m 的 comparator } /**{@inheritDoc}**/ public E first() { return m.firstKey(); } /**{@inheritDoc}**/ public E last() { return m.lastKey(); //返回 m 中的最后一个键 } // 导航 API 方法 /**{@inheritDoc}**/ public E lower(E e) { return m.lowerKey(e); //m 调用 lowerKey 方法,接收参数为 e,返回 } /**{@inheritDoc}**/ public E floor(E e) { return m.floorKey(e); //m 调用 floorKey 方法,接收参数为 e,返回 } /**{@inheritDoc}**/ public E ceiling(E e) { return m.ceilingKey(e); //m 调用 ceilingKey 方法,接收参数为 e,返回 } /**{@inheritDoc}**/ public E higher(E e) { return m.higherKey(e); //m 调用 higherKey 方法,接收参数为 e,返回 } /****/ public E pollFirst() { Map.Entry<E,?> e = m.pollFirstEntry(); //调用 m.pollFirstEntry 方法,缓存结果给 e return (e == null) ? null : e.getKey(); //比较 e == null,如果是返回 null,否则返回 e.getKey } /****/ public E pollLast() { Map.Entry<E,?> e = m.pollLastEntry(); //调用 m.pollLastEntry 方法,缓存结果给 e return (e == null) ? null : e.getKey(); //比较 e == null,如果是返回 null,否则返回 e.getKey } /** * 返回当前 {@code TreeSet} 实例的浅拷贝。(元素没有被克隆) */ @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); //构造一个 TreeMap,参数为 m,赋值给 clone.m return clone; } /** * 序列化写,保存 {@code TreeSet} 的状态到一个流中。 */ 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); } /** * 序列化读,从流中构建出一个 {@code TreeSet} 实例。 */ 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); } /** * 返回一个包含当前 set 中所有元素的延迟绑定和 fail-fast 的并行迭代器。 */ public Spliterator<E> spliterator() { return TreeMap.keySpliteratorFor(m); } private static final long serialVersionUID = -2479143000061671589L; }

通过 TreeSet 的源码我们可以看到,TreeSet 的顺序是在构造时候通过传入与 comparable/comparator 有关的参数来实现的,而它与 HashSet 类似,通过持有一个 Map 实例(这次是 TreeMap)并操作这个 map 来达到看上去在操作一个 set 的目的,所以 TreeSet 也就是一种装饰器模式而已,TreeSet 的真正实现就是 TreeMap。

以上就是对于 Set 接口的最终实现类 TreeSet 的介绍与分析,下一篇就将开始介绍 Map 数据结构。

你可能感兴趣的:(Java,8,数据结构)