我们简要地看了一下集合框架的接口,这些接口定义了我们可以预期的每个集合的行为。但正如我们在本章的介绍中提到的,有几种方法可以实现每个接口。为什么框架不会 为每个接口使用最佳实现?那肯定会让生活变得更简单 - 事实上,过于简单就像生活一样。如果实施对某些行动来说是灰狗,墨菲定律告诉我们这对其他人来说将是一只乌 龟。由于没有任何接口的“最佳”实现,所以您必须进行权衡,判断应用程序中哪些操作最常使用,并选择优化这些操作的实现。
大多数集合接口需要的三种主要操作是按位置插入和移除元素,按内容检索元素以及迭代集合元素。这些实现在这些操作上提供了许多变体,但它们之间的主要区别可以从它 们如何实现这三个方面来讨论。在本节中,我们将简要考察用作实现基础的四个主要结构,随后,当我们需要它们时,我们将更详细地查看每个结构。这四种结构是:
数组
- 这些是来自
Java
语言熟悉的结构 - 自Fortran
以来几乎所有其他编程语言。 因为数组是直接在硬件中实现的,所以它们具有随机存取内存的特性:按位置访问 元素并迭代它们非常快,但在任意位置插入和移除元素的速度较慢(因为这可能需要调整位置 其他元素)。 在集合框架中中使用数组作为ArrayList
,CopyOnWriteArrayList
,EnumSet
和EnumMap
以及许多Queue
和Deque
实现的支持结构。 它们也是实现散列表机制的一个重要部分(稍后讨论)。
链接列表
- 顾名思义,它们由链式单元链组成。 每个单元格都包含对数据的引用和对列表中下一个单元格的引用(以及在某些实现中的前一个单元格)。 链接列表的执行方式与数组
完全不同:按位置访问元素的速度很慢,因为必须从列表的开始处跟随引用链,但可以通过重新排列单元格引用来在不变的时间内执行插入和删除操作。 链接列表是用于类
ConcurrentLinkedQueue
,LinkedBlockingQueue
和LinkedList
以及新的跳过列表集合ConcurrentSkipListSet
和ConcurrentSkipListMap
的主 要支持结构。 它们也用于实现HashSet
和LinkedHashSet
。
哈希表
- 这些提供了一种存储在其内容上索引的元素的方法,而不是像列表那样在整数值索引上存储索引。 与数组和链表相比,散列表不支持按位置访问元素,但内容访问通常非
常快速,就像插入和删除一样。 哈希表是许多
Set
和Map
实现的支持结构,包括HashSet
和LinkedHashSet
以及相应的映射HashMap
和LinkedHashMap
,以及WeakHashMap
,IdentityHashMap
和ConcurrentHashMap
。
树
- 这些也按内容来组织它们的元素,但重要的区别是它们可以按排序顺序存储和检索它们。它们对于插入和删除元素,通过内容访问它们并迭代它们的操作相对较快。 树是
TreeSet
和TreeMap
的支持结构。 在执行PriorityQueue
和PriorityBlockingQueue
时使用的优先堆是与树有关的结构。