系列中的上一篇
当前教程
了解集合层次结构
系列中的下一篇

系列中的上一篇: 使用集合框架存储数据

系列中的下一篇: 在集合中存储元素

了解集合层次结构

 

避免在集合层次结构中迷路

集合框架分为多个接口和类的层次结构。您需要理解的第一个层次结构如下:集合接口层次结构。

The Collection Interface Hierarchy

集合接口层次结构

请注意,一些接口已被省略,您将在后面看到它们。

 

Iterable 接口

此层次结构的第一个接口是 Iterable 接口,实际上它不属于集合框架。在这里提一下它仍然很有价值,因为它 是 Collection 接口的超接口,因此也是此层次结构中所有接口的超接口。

The Iterable 接口是 Java SE 5 (2004) 的新增内容。实现 Iterable 的对象是可以迭代的对象。它是在 Java SE 5 中与for each 代码模式一起添加的。

您可能已经熟悉这种迭代 Collection 元素的方法。

Collection<String> collection = ...; 

for (String element: collection) {
    // do someting with element
}

您可能已经知道可以使用此模式或任何数组迭代任何集合。事实证明,实际上任何 Iterable 实例都可以在此处使用。

实现 Iterable 接口非常容易:您只需提供另一个接口的实例,Iterator,您将在下面看到它。

 

使用 Collection 接口在容器中存储元素

所有其他接口都与在容器中存储元素有关。

两个接口 ListSet 都具有共同的行为,这些行为由 Collection 接口建模。The Collection 接口对元素容器建模了多个操作。在不深入技术细节的情况下(暂时!),以下是可以使用 Collection 执行的操作:

  • 添加或删除元素;
  • 测试给定元素的存在;
  • 询问包含的元素数量,或此集合是否为空;
  • 清除此内容。

由于 Collection 是元素的集合,因此在 Collection 接口上也定义了集合操作:

  • 测试一个集合是否包含在另一个集合中;
  • 并集;
  • 交集;
  • 补集。

最后,Collection 接口还对访问其元素的不同方式进行建模:

  • 您可以通过使用迭代器迭代集合的元素;
  • 您可以对这些元素创建流,这些流可以是并行的。

当然,所有这些操作在 ListSet 上也可用。那么,普通 Collection 实例与 Set 实例或 List 实例之间有什么区别?

 

使用 List 扩展 Collection

元素 List 与元素 Collection 之间的区别在于,List 会记住元素添加的顺序。

第一个结果是,如果您迭代列表的元素,您将获得的第一个元素是第一个添加的元素。然后您将获得第二个元素,依此类推,直到所有元素都被看到。因此,您迭代元素的顺序始终相同,它由这些元素添加的顺序固定。对于普通 CollectionSet,您没有这种保证。

事实证明,集合框架提供的 Set 的某些实现恰好始终以相同的顺序迭代元素。这是一个意外的效果,您的代码不应依赖此行为。

还有一个第二个结果,可能不像第一个结果那么明显,即列表的元素具有索引。查询集合的第一个元素没有意义。查询列表的第一个元素是有意义的,因为列表确实会记住这一点。

这些索引是如何处理的?好吧,再一次,这是实现的责任。接口的第一个作用是指定行为,而不是告诉实现应该如何实现该行为。

正如您将看到的那样,List 接口在 Collection 接口中添加了新的操作。由于列表的元素具有索引,因此您可以使用该索引执行以下操作。

  • 获取特定索引处的元素,或删除它
  • 在特定位置插入元素或替换元素
  • 获取两个索引之间的元素范围。

 

使用 Set 扩展 Collection

元素 Set 与元素 Collection 之间的区别在于,您不能在 Set 中拥有重复项。您可以在 Collection 中拥有多个相同类的实例,这些实例是相等的,甚至可以拥有同一个实例多次。这在 Set 中是不允许的。如何强制执行这是实现的责任,您将在本教程的后面看到这一点。

这种行为的结果之一是,将元素添加到 Set 中可能会失败。

然后您可能会问自己:我可以拥有一个容器来防止重复,并且在其中元素具有索引吗?答案并不简单。集合框架为您提供了一个 Set 实现,使用它您将始终以相同的顺序迭代元素,但这些元素没有索引,因此此类不实现 List

这种行为上的差异不会在 Set 接口中带来任何新的操作。

 

使用 SortedSet 和 NavigableSet 对 Set 的元素进行排序

The Set 接口本身有两个扩展:SortedSetNavigableSet.

The SortedSet 接口按升序维护其元素。再一次,如何强制执行这是实现的责任,正如您将在后面看到的那样。

为了能够对它们进行排序,SortedSet 需要比较您的元素。它如何实现这一点?好吧,Java 语言中定义了两种标准机制来实现这一点。

即使您的元素是 Comparable,您仍然可以在构建 SortedSet 时提供一个 Comparator。如果您需要以不同于 compareTo() 方法中实现的顺序对元素进行排序,这将非常有用。

排序和排序有什么区别?List 按添加元素的顺序保存其元素,而 SortedSet 按排序顺序保存其元素。对元素进行排序意味着,在遍历集合时获得的第一个元素将是最小的元素,从给定的比较逻辑的角度来看。对元素进行排序意味着,您在列表中添加元素的顺序在该列表的生命周期内保持不变。因此,在遍历列表时获得的第一个元素是添加到列表中的第一个元素。

SortedSetSet 添加了一些操作。以下是您可以使用 SortedSet 执行的操作。

  • 您可以获取集合中最小的元素和最大的元素。
  • 您可以提取一个 headSet 和一个 tailSet,分别包含小于或大于给定元素的所有元素。

遍历 SortedSet 中的元素将从最小元素到最大元素进行。

NavigableSet 不会改变 SortedSet 的行为。它在 SortedSet 上添加了一些非常有用的操作,其中包括以降序遍历元素的可能性。您将在后面看到更多关于这方面的细节。


上次更新: 2021 年 9 月 14 日


系列中的上一篇
当前教程
了解集合层次结构
系列中的下一篇

系列中的上一篇: 使用集合框架存储数据

系列中的下一篇: 在集合中存储元素