系列中的上一篇
当前教程
使用 Set、SortedSet 和 NavigableSet 扩展集合

系列中的上一篇: 使用 List 扩展集合

系列中的下一篇: 使用集合工厂方法创建和处理数据

使用 Set、SortedSet 和 NavigableSet 扩展集合

 

探索 Set 接口

Set 接口没有为 Collection 接口带来任何新方法。集合框架为您提供了一个 Set 接口的简单实现:HashSet。在内部,HashSet 包装了一个 HashMap 实例,该类将在后面介绍,它充当 HashSet 的代理。

正如您已经看到的,SetCollection 带来的好处是它禁止重复。与 List 接口相比,您失去的是元素以无特定顺序存储。您几乎不可能以与添加到集合中的顺序相同的顺序遍历它们。

您可以在以下示例中看到这一点

List<String> strings = List.of("one", "two", "three", "four", "five", "six");
Set<String> set = new HashSet<>();
set.addAll(strings);
set.forEach(System.out::println);

运行此代码将产生以下结果

six
four
one
two
three
five

一些 Set 的实现会在您遍历其元素时为您提供相同的顺序,但由于这不是保证的,因此您的代码不应依赖于此。

 

使用 SortedSet 扩展 Set

Set 的第一个扩展是 SortedSet 接口。 SortedSet 接口根据特定的比较逻辑对其元素进行排序。集合框架为您提供了一个 SortedSet 实现,称为 TreeSet

正如您已经看到的,您可以在构建 TreeSet 时提供比较器,或者为放入 TreeSet 的元素实现 Comparable 接口。如果您同时执行这两项操作,则比较器优先。

SortedSet 接口为 Set 添加了新方法。

toElementfromElement 不必是主集合的元素。如果它们是,则 toElement 不包含在结果中,而 fromElement 包含在结果中,遵循通常的约定。

请考虑以下示例

SortedSet<String> strings = new TreeSet<>(Set.of("a", "b", "c", "d", "e", "f"));
SortedSet<String> subSet = strings.subSet("aa", "d");
System.out.println("sub set = " + subSet);

运行此代码将为您提供以下结果

sub set = [b, c]

这些方法返回的三个子集是主集合的视图。不会进行任何复制,这意味着您对这些子集进行的任何更改都将反映在集合中,反之亦然。

您可以通过这些子集删除或添加主集合中的元素。不过,您需要注意一点。这三个子集会记住它们构建的限制。出于一致性原因,通过子集添加超出其限制的元素是非法的。例如,如果您获取一个 headSet 并尝试添加大于 toElement 的元素,那么您将得到一个 IllegalArgumentException

 

使用 NavigableSet 扩展 SortedSet

Java SE 6 引入了 SortedSet 的扩展,并添加了更多方法。事实证明,TreeSet 类已进行改造以实现 NavigableSet。因此,您可以对这两个接口使用相同的类。

一些方法被 NavigableSet 重载。

  • headSet()tailSet()subSet() 可以接受一个额外的 boolean 参数来指定是否将限制(toElementfromElement)包含在结果子集中。

添加了其他方法。

  • ceiling(element)floor(element) 返回小于或等于提供的 element 的最大元素,或大于或等于提供的 element 的最小元素。如果没有这样的元素,则返回 null
  • lower(element)higher(element) 返回小于提供的 element 的最大元素,或大于提供的 element 的最小元素。如果没有这样的元素,则返回 null
  • pollFirst()pollLast() 返回并删除集合中最小的或最大的元素。

此外,NavigableSet 还允许您以降序遍历其元素。有两种方法可以做到这一点。

  • 您可以调用 descendingIterator():它为您提供一个常规的 Iterator,它以降序遍历集合。
  • 您还可以调用 descendingSet()。您得到的返回值是另一个 NavigableSet,它是此集合的视图,让您感觉您拥有的是同一个集合,只是以相反的顺序排序。

以下示例演示了这一点。

NavigableSet<String> sortedStrings = new TreeSet<>(Set.of("a", "b", "c", "d", "e", "f"));
System.out.println("sorted strings = " + sortedStrings);
NavigableSet<String> reversedStrings = sortedStrings.descendingSet();
System.out.println("reversed strings = " + reversedStrings);

运行此代码将为您提供以下结果

sorted strings = [a, b, c, d, e, f]
reversed strings = [f, e, d, c, b, a]

上次更新: 2021 年 9 月 14 日


系列中的上一篇
当前教程
使用 Set、SortedSet 和 NavigableSet 扩展集合

系列中的上一篇: 使用 List 扩展集合

系列中的下一篇: 使用集合工厂方法创建和处理数据