简介
在java的包java.util和java.util.concurrent里面定义了java的集合类框架。我们大部分日常使用到的数据结构都可以在这里找到一个对应的实现。在以往的学习过程中可能会接触过一些具体的结构。但是对于java集合类框架来说,他里面包含有哪些类别的结构呢?对于不同的结构,他们分别适用于哪些应用场景?集合类框架中这些类之间是否有着某种关系呢?在这里,我们尝试对所有这些集合类做一个总结。
总体结构
从总体来看,我们可以将集合类划分为两个大的部分。一种是可以按照一定顺序进行迭代访问的集合类。一种是通过名值对的映射建立关系进行访问的集合类。这两种集合类型分别构成了不同的类继承结构。对于可以迭代访问的集合类来说,他们主要的接口定义关系如下图所示:
从前面的定义结构图我们可以看到。对于这个结构里面的所有接口,他们都继承自接口Iterable。而Iterable接口定义了用于迭代访问的协议。从某个角度来说,这也是为了方便我们后续可以使用foreach的方式来遍历这里所有集合类的元素。Iterable接口也和Iterator设计模式有紧密的关系。关于他们关系的描述详情可以参考我的另外一篇文章。 对于其他常见的几种类型,比如说Set, List, Queue等都是继承了Collection接口。关于这几种具体的类型我们在后续部分会详细介绍。
除了我们上述提到的可以迭代遍历的数据结构类型以外,我们还有一种就是名值对的结构,主要是继承自Map接口:
我们很多常用的数据结构,比如说HashMap, TreeMap, HashSet, TreeSet都是继承自这一系列接口。下面,我们再针对每个类别做一个更加详细的分析。
Collection
Collection接口是所有后续集合类型的一个公共抽象定义。它本身没有一个直接的实现,更多的是各种不同的集合类型在它的基础上继承了更多特殊的特性并做了一个实现。Collection接口里主要定义了一些作为集合类型比较通用的方法,比如说size, isEmpty, add, remove等。作为集合类型比较通用的一个定义,它主要用在一些需要比较高级别抽象的地方。比如说我们需要可以对所有集合类型进行通用操作。
Set
Set定义的是数学意义上的集合类型,通常里面的元素是要求不能重复的。它定义的系列类结构如下图:
在常用的集合类型中,HashSet, TreeSet等具体的实现往往不一样。比如说HashSet本身的实现是引用了HashMap作为内部的元素。如果我们仔细检查他们的结构实现,会发现有的类型我们也可以通过foreach的循环来遍历。这是因为他们有的在实现Set定义接口的范围同时也继承了实现Collection接口的部分。可以说是两者兼有之。
在上面这些集合类型中,基于Hash表实现的主要有HashSet, LinkedHashSet。基于红黑树实现的有TreeSet.另外,CopyOnWriteArraySet内部的实现是采用了一个CopyOnWriteArrayList,这种数据结构有一个比较有意思的实现。对它调用某些增删元素的方法会产生一个全新的对象。这充分利用了immutable对象的实现思路,在并行程序的开发中有一定的应用。
List
List类型的数据结构算是我们平时接触最多而且看起来最简单的数据结构类型。最常用的两种是ArrayList和LinkedList,也就是我们常说的线性表和链表。线性表的结构一般如下图:
对于线性表结构来说,它对于元素的随机访问比较快。对于表中间任意一个元素的访问,只需要映射到索引下标就可以了。但是,由于要保证线性表的连贯性,如果删除了表中间的元素,则需要对表进行元素移动,从而影响到它的执行效率。典型的ArrayList除了上述的特性以外还有一个比较显著的特点就是它可以根据需要自动增长。就是说,我们新建一个List对象的时候它有一个默认的长度,但是当我们往里面添加元素一直到这个表满了,则ArrayList会自动将自己的容量翻倍,再将元素放到这个新的列表里。
另外一种典型的List就是链表,它的结构如下图:
在链表中,我们对一个元素的访问一般是需要从头到尾的去遍历。只有找到需要操作的成员才能进行操作。所以我们对链表元素进行随机访问时效率会比较慢。不过对于元素的增删操作则比较快。因为只需要调整链表指针就可以了。我们可以根据需要选择合适的List数据类型。在JDK的内部实现里没有直接提供一个单链表的实现,LinkedList实际上是一个双向链表。关于ArrayList和LinkedList的详细实现分析可以参照我的这篇文章。
除了我们提到的这两种线性表结构,我们以前学习到的Stack, Queue等数学结构,很多也是内部采用线性表结构。比如说Stack内部实现是采用了Vector,而LinkedList本身也继承了Queue接口,提供了一个Queue的实现。这些详细的讨论也可以参考我的Stack分析和Queue分析文章。
Queue
对于Queue类型的数据结构来说,他本身的特性是要满足先进先出。它可以分为单队列和双端队列,具体的实现可以是数组也可以是链表。几个典型的Queue相关的类关系图如下:
最常见的几种Queue的数据类型有LinkedList, ArrayDeque, PriorityQueue。他们都最终实现了Queue接口。不过PriorityQueue稍微特殊一点,它本身是实现一个排序效果的队列。关于PriorityQueue的分析可以参考我另外一篇对于它源代码的分析文章。
Map
Map类型的数据结构重点在于一个名值对的集合体。它本身要保证里面有一个名字的键值作为元素的唯一识别,并关联对应的值。所以,如果我们去查看Map的的定义,里面会有很多关于键值和对应值的操作,比如说containsKey, containsValue,V get(Object key), V put(K key, V value)等方法。我们常用的HashTable, HashMap, TreeMap, ConcurrentHashMap都是对应Map接口的具体实现。
其中HashTable和HashMap是一种经典的哈希表实现,在很多面试的过程中也会讨论到这些问题。HashMap内部实现是使用一个数组,每个数组的元素又构成了一个链表结构。这可以说是教科书上定义的哈希表的一个经典实现。另外TreeMap的实现是使用了数据结构里面的红黑树,它可以保证里面所有的元素访问操作都是排序的,而且操作的时间复杂度都是在logN的级别。而对于ConcurrentHashMap来说,它内部是采用了分段,并对不同段采用独立的锁的机制进行设计,尽可能保证足够大的并行度。对于HashMap和TreeMap的具体实现分析也可以参照我的几篇文章(HashMap篇,TreeMap篇)。后续还会对ConcurrentHashMap的实现做一个详细分析。
总结
在这里,我们针对Java集合类中间主要的几种类型都做了一个描述和分析。按照一种不太严格的划分,Java集合类中大体包括可遍历的和名值对映射两种大类别。在实际实现的很多数据结构里兼有这两者的特性。对于遍历数据类型来说,主要包括有Set, List, Queue几个大类。而对于名值对映射的里面主要是对应Map接口的实现。常用的有SortedMap, ConcurrentMap。我们用到的HashMap是一种非排序的Map实现,而TreeMap是内部机制实现了排序的。另外,对于一些适合并行编程操作的数据结构来说,他们本身有的利用了immutable的机制实现有效的隔离效果,比如CopyOnWriteArrayList;有的利用一些内部加锁的机制来保证一定程度的并行性,比如说ConcurrentHashMap。在后续的一些文章里会重点针对这些并行的数据结构集合类型进行讨论。
参考材料
相关推荐
Java 集合框架(JCF:Java Collections Framework)之概述 Java 集合框架(JCF:Java Collections Framework)是 Java 语言中的一组类库,用于实现集合操作的统一标准。集合是计算机科学中的一种基本概念,来源于...
- **教程概述**:本教程由 developerWorks 提供,旨在帮助读者深入理解 Java Collections Framework 的各个方面。 - **适用人群**: - **初学者**:教程以简单的编程示例为起点,使初学者能够快速上手。 - **高级...
《APress - Java Collections》这本书由John Zukowski编写,深入探讨了Java集合框架的各种细节,为读者提供了理解和应用Java集合类的重要知识。本书版权属于作者John Zukowski,并于2001年出版,所有权利受法律保护...
1. 集合框架概述:在深入探讨之前,首先要了解集合框架的整体结构,包括它是如何组织各种不同的集合类以及它们是如何相互关联的。Java集合框架被分为两大类:Collection接口,主要处理一组单一元素,以及Map接口,...
6. **工具类**:除了集合类本身之外,Java还提供了一些工具类,如`Collections`,它包含了各种静态方法,用于对集合进行操作,如排序、查找、填充等。 #### 四、案例分析 1. **使用ArrayList存储字符串**: ```...
泛型允许集合类声明其元素的具体类型,从而避免了运行时的类型转换错误,并确保类型安全性。 **示例代码**: ```java List<String> strings = new ArrayList(); strings.add("Hello"); String str = strings.get(0)...
此外,教程还讨论了Java Collections Framework的历史背景,澄清了围绕多种类似集合类出现所带来的一些困惑。 #### 二、Java Collections Framework概述 Java Collections Framework是Java标准库的一部分,提供了...
在Java编程语言中,集合类框架(Collections Framework)提供了处理数据的强大工具。本篇文章将详细介绍三种主要的集合类型:`List`、`Set` 和 `Map` 的特性、区别及联系。 #### 二、`List` 集合 **特点**: - ...
Java 集合框架概述 Java 集合框架是 Java 语言中提供的一种统一的标准体系结构,用于表示和操作集合。集合框架包含三大块内容:对外的接口、接口的实现和对集合运算的算法。 1. 接口:Collection 顶层接口是集合...
### Java Collections中的Fail Fast机制详解 #### 一、概述 在Java编程中,**Fail Fast**机制是一项重要的设计原则,特别是在处理集合时尤为关键。它主要用于确保数据结构的一致性和完整性,通过快速检测并报告...
- `Vector`: 是一种线程安全的动态数组实现,但在现代Java开发中很少使用,因为它相较于其他非线程安全的集合类来说性能较差。 #### 三、Iterator 迭代器(接口) **1. Iterator 接口** - `Iterator`接口用于遍历...
为了支持多线程环境下的并发操作,Java 集合框架还提供了并发集合类,如 `ConcurrentHashMap` 和 `CopyOnWriteArrayList`。 #### 五、总结 通过对 Java 集合框架的深入理解,开发者可以更好地利用这些工具来提高...
《Java Collections》这本书全面介绍了Java集合框架的相关知识,不仅涵盖了核心概念和常用类,还涉及了高级主题如性能优化和并发处理。通过学习本书,读者能够深刻理解Java集合的工作原理,从而更加高效地使用这些...
Java库的不可变集合(JImmutable Collections)是一组高性能的不可变集合,用于替换或补充标准的java.util集合。 为每个最常用的集合提供功能替换: Java类 JImmutable接口 工厂方法 数组列表 JImmutableList ...
本书深入探讨了Java平台中的集合类,提供了丰富的示例和实践指导,对于希望深入了解Java集合框架的开发人员来说是一本非常有价值的参考书籍。 #### 书籍版权与出版信息 本书版权所有归John Zukowski所有,并由...
Java 集合框架概述 Java 集合框架是 Java 语言中对对象进行存储和操作的方式。集合框架提供了多种方式来存储和操作对象,包括 List、Set、Map 等。集合框架的主要特点是可以存储多个对象,并且可以对这些对象进行...
#### 三、集合类概述 Java中的集合类位于`java.util`包中,主要包括三种类型:Set(集)、List(列表)和Map(映射)。每种类型的集合都有其特点和应用场景。 #### 四、Set(集) Set是一种不允许重复元素的集合,...
7. **集合类的介绍与应用:** - Sets(集):不允许包含重复元素的集合。 - Queues(队列):一种先进先出的数据结构。 - Lists(列表):有序集合,允许包含重复元素。 - Maps(映射):存储键值对的数据结构。...
Java集合框架分为两大类:Collection和Map。Collection接口是单值容器,包含List和Set子接口;Map接口是键值对容器,用于存储键-值对的数据。 ### Collection 1.2.1 常用方法 Collection接口定义了许多通用方法,...