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

本文详细介绍了Java 8中的TreeSet数据结构,包括其继承结构、SortedSet和NavigableSet接口的功能,以及如何通过comparable/comparator实现元素排序。通过对源码的分析,揭示了TreeSet其实质是装饰器模式,内部依赖于TreeMap来实现有序的Set操作。
摘要由CSDN通过智能技术生成

前言

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

先来看下 TreeSet 完整的继承结构图
在这里插入图片描述

可以看到 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 的视图,包括:<pre>
 *   SortedSet<String> sub = s.subSet(low, high+"\0");</pre>
 *
 * 一个类似的技术可以用来生成一个开放区间(两个端点都不包含)。下列惯用语义包含了一个所有 
 * s 中从 low 到 high 的视图,包括:<pre>
 *   SortedSet<String> sub = s.subSet(low+"\0", high);</pre>
 * 
 * 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><
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值