SortedSet interface

SortedSetSet,它按照其自然 Sequences 或在SortedSet创建时提供的Comparator排序,以升序维护其元素。除了正常的Set操作之外,SortedSetinterface还提供以下操作:

  • Range view-允许对排序后的集合进行任意范围的操作

  • Endpoints —返回排序集中的第一个或最后一个元素

  • Comparator access —返回用于对集合进行排序的Comparator(如果有)

SortedSetinterface的代码如下。

public interface SortedSet<E> extends Set<E> {
    // Range-view
    SortedSet<E> subSet(E fromElement, E toElement);
    SortedSet<E> headSet(E toElement);
    SortedSet<E> tailSet(E fromElement);

    // Endpoints
    E first();
    E last();

    // Comparator access
    Comparator<? super E> comparator();
}

Set Operations

SortedSetSet继承的操作在排序集和普通集上的行为相同,但有两个 exception:

  • iterator操作返回的Iterator按 Sequences 遍历排序后的集合。

  • toArray返回的数组按 Sequences 包含排序的集合的元素。

尽管interface不能保证它,但是 Java 平台SortedSet实现的toString方法按 Sequences 返回一个字符串,其中包含排序后的集合的所有元素。

Standard Constructors

按照惯例,所有通用Collection实现都提供一个采用Collection的标准转换构造函数; SortedSet实现也不 exception。在TreeSet中,此构造函数创建一个实例,该实例根据其元素的自然 Sequences 对其进行排序。这可能是一个错误。最好动态检查以查看指定的集合是否为SortedSet实例,如果是,则根据相同的标准(比较器或自然排序)对新的TreeSet进行排序。因为TreeSet采用了它所采用的方法,所以它还提供了一个构造器,该构造函数采用SortedSet并返回一个新的TreeSet,该TreeSet包含根据相同条件排序的相同元素。请注意,确定调用这两个构造函数中的哪一个(以及是否保留排序标准)的是参数的编译时类型,而不是其运行时类型。

按照惯例,SortedSet实现也提供了一个构造器,该构造器采用Comparator并返回根据指定的Comparator排序的空集。如果null传递给此构造函数,它将返回一个集合,该集合根据其自然 Sequences 对元素进行排序。

Range-view Operations

range-view操作与Listinterface提供的操作有些相似,但是有一个很大的区别。即使直接修改了支持排序的集合,排序的集合的范围视图仍然有效。这是可行的,因为排序集的范围视图的端点是元素空间中的绝对点,而不是后备集合中的特定元素(如列表)。排序后的集合的range-view实际上只是该集合的任何部分位于元素空间的指定部分中的窗口。对range-view的更改将写回到后备排序集,反之亦然。因此,可以在排序的集合上 Long 时间使用range-view,而与列表上的range-view不同。

排序的集合提供了三个range-view操作。第一个subSet具有两个端点,例如subList。端点不是对象,而是索引,而不是索引,它们必须与SetComparator或其元素的自然 Sequences(无论Set用来对其自身进行排序)的排序集合中的元素相当。像subList一样,范围是半开的,包括其低端点,但不包括高端点。

因此,以下代码行告诉您SortedSet字符串dictionary中包含"doorbell""pickle"之间的多少个单词,包括"doorbell"但不包括"pickle"

int count = dictionary.subSet("doorbell", "pickle").size();

以类似的方式,下面的单行删除所有以字母f开头的元素。

dictionary.subSet("f", "g").clear();

可以使用类似的技巧来打印表格,以告诉您每个字母以多少个单词开头。

for (char ch = 'a'; ch <= 'z'; ) {
    String from = String.valueOf(ch++);
    String to = String.valueOf(ch);
    System.out.println(from + ": " + dictionary.subSet(from, to).size());
}

假设您要查看一个包含两个端点的封闭时间间隔,而不是一个开放时间间隔。如果元素类型允许计算元素空间中给定值的后继元素,则仅请求subSetlowEndpointsuccessor(highEndpoint)即可。尽管并不完全清楚,但按String的自然 Sequences 排列的字符串s的后继者是s + "\0",即s附加了null字符。

因此,下面的单行代码会告诉您词典中包含"doorbell""pickle"之间的词,包括门铃和 pickle。

count = dictionary.subSet("doorbell", "pickle\0").size();

可以使用类似的技术来查看一个开放时间间隔,其中不包含任何端点。从lowEndpointhighEndpoint的打开间隔视图是从successor(lowEndpoint)highEndpoint的半打开间隔。使用以下内容计算"doorbell""pickle"之间的字数,但不包括两者。

count = dictionary.subSet("doorbell\0", "pickle").size();

SortedSetinterface包含另外两个range-view操作-headSettailSet,它们都带有一个Object参数。前者返回背面SortedSet的初始部分的视图,直到但不包括指定的对象。后者返回背衬SortedSet的最后部分的视图,从指定的对象开始,一直到背衬SortedSet的结尾。因此,以下代码允许您将字典视为两个不相交的volumes(a-mn-z)。

SortedSet<String> volume1 = dictionary.headSet("n");
SortedSet<String> volume2 = dictionary.tailSet("n");

Endpoint Operations

SortedSetinterface包含用于返回排序集中的第一个和最后一个元素的操作,这并不奇怪,它们称为firstlast。除了它们的明显用途之外,last还允许解决SortedSetinterface中的缺陷。您想对SortedSet进行的一件事是进入Set的内部并向前或向后迭代。从内部前进很容易:只需获得tailSet并对其进行迭代。不幸的是,没有简单的方法可以退后。

以下成语获得元素空间中小于指定对象o的第一个元素。

Object predecessor = ss.headSet(o).last();

这是从已排序集合内部的某个点向后退一个元素的好方法。可以重复应用它以进行向后迭代,但这效率很低,需要对返回的每个元素进行查找。

Comparator Accessor

SortedSetinterface包含一个称为comparator的访问器方法,该方法返回用于对集合进行排序的Comparator,如果该集合是根据其元素的自然 Sequences 进行排序的,则返回null。提供此方法,以便可以将排序后的集合以相同的 Sequences 复制到新的排序后的集合中。由previously描述的SortedSet构造函数使用。