使用 Set、SortedSet 和 NavigableSet 扩展集合
探索 Set 接口
Set
接口没有为 Collection
接口带来任何新方法。集合框架为您提供了一个 Set
接口的简单实现:HashSet
。在内部,HashSet
包装了一个 HashMap
实例,该类将在后面介绍,它充当 HashSet
的代理。
正如您已经看到的,Set
为 Collection
带来的好处是它禁止重复。与 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
接口。如果您同时执行这两项操作,则比较器优先。
first()
和last()
返回集合中最小的和最大的元素headSet(toElement)
和tailSet(fromElement)
返回包含小于toElement
或大于fromElement
的元素的子集subSet(fromElement, toElement)
为您提供fromElement
和toElement
之间元素的子集。
toElement
和 fromElement
不必是主集合的元素。如果它们是,则 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
重载。
添加了其他方法。
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 日